Motivation

BMI is measured as an individual’s weight in kilograms divided by the individual’s height in meters squared. Different categories of weight are defined with the following cutoffs:

An article published in Nature evaluated and compared the Body-Mass Index (BMI) of populations in rural and urban communities around the world:

NCD Risk Factor Collaboration (NCD-RisC). Rising rural body-mass index is the main driver of the global obesity epidemic in adults. Nature 569, 260–264 (2019).

This article challenged the widely-held view that increased urbanization was one of the major reasons for increased global obesity rates. This view came about because many countries around the world have shown increased urbanization levels in parallel with increased obesity rates. However this study demonstrated that this might not be the case. This case study will evaluate the data reported in this article to explore regional and gender specific differences in the obesity rates around the world in 1985 and 2017. Most importantly we will test if there is a difference in obesity rates between rural and urban communities.

Our main questions are:

  1. Is there a difference between rural and urban BMI estimates around the world?
  2. How have BMI estimates changed from 1985 to 2017?
  3. How do different countries compare for BMI estimates- in particular, how does the United States compare to the rest of the world?

In this case study, we’ll walk you through importing data from a pdf, cleaning data, wrangling data, visualizing the data, and comparing the means of two groups using well-established and commonly used packages, including stringr, tidyr, dplyr, purrr, and ggplot2. We will especially focus on using packages and functions from the Tidyverse. The Tidyverse is a library of packages created by the chief scientist at RStudio, Hadley Wickham. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.

We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
pdftools to read a pdf into R
stringr to manipulate the text within the pdf of the data
readr to manipulate the text within the pdf of the data into individual lines
dplyr to arrange/filter/select subsets of the data
tibble to create data objects that we can manipulate with dplyr/stringr/tidyr/purrr
magrittr to use the %<>% pipping operator
purrr to perform functions on all columns of a tibble
tidyr to convert data from wide to long format
ggplot2 to make visualizations with multiple layers
data.table to create data objects that are similar to tibbles but different
ggrepel to allow labels in figures not to overlap
cowplot to allow plots to be combined

The first time we use a function, we will use the :: to indicate what package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to illustrate what package we are using.

Context

The measurement of BMI has some limitations that are well recognized, as it does not account for the composition of body mass, the location of body fat, or the contribution of body frame size. However, BMI has been a useful health indicator for risk for many diseases particularly when combined with other risk factor information.

What are the data?

We will be using data located within a table of the supplementary material for the NCD-RisC paper referenced above. This is a pdf that can be found freely available online.

Here you can see that the data contains mean BMI values for both Men and Women in various countries at the national level, as well as the mean BMI values for the rural and urban areas of these countries for both 1985 and 2017.

The data within the parentheses are the 95 % credible interval (CIs) ranges for the mean BMI estimates. The authors provide these CIs as a guide to understand how likely the estimate is for the true population mean BMI. A wider range suggests that the estimate is less accurate, as there are more possible values for the true mean with credible evidence.

Note: While gender and sex are not actually binary, the data presented that is used in this analysis only contains data for groups of individuals described as men or women.

Data Import

First let’s download the data:

Now that we have the obesity pdf, we will read it in to R using the pdftools package:

Let’s take a look at the data- the summary() function helps us to look at the structure of R objects.

   Length     Class      Mode 
       63 character character 

We can see that we have 63 elements that are character strings. You may also notice that the original PDF has 63 pages. Let’s take a look at some of these elements.

[1] "Letter                                                                                https://doi.org/10.1038/s41586-019-1171-x\nRising rural body-mass index is the main driver of\nthe global obesity epidemic in adults\nNCD Risk Factor Collaboration (NCD-RisC)*\n*A list of authors and their affiliations appears in the online version of the paper.\n2 6 0 | N A T U RE | V O L 5 6 9 | 9 M A Y 2 0 1 9\n"
[1] "Supplementary Information. Statistical model for estimating BMI trends by rural and urban\nplace of residence.\n                                          1\n"

We can see that the output looks pretty similar to the pages of the pdf, but the spacing is quite awkward. The way the data is displayed is partially influenced by how width setting of the RStudio window.

We are interested in a supplementary Table 3. which has multiple pages and includes the same header on each page; we can use that to determine what elements of our pdf_obesity character strings include our table. We will use the str_detect() function of the stringr package to search for the elements that contain text that is consistently in the header. The output of of this function will show which elements of the object (in this case pages of the pdf) include this pattern indicated as a “TRUE” or “FALSE”.

 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[12] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[23] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[34] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[45] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
[56]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE

Let’s extract just the data for the table now and call it rural_urban.

 chr [1:10] "                                                                          2                                    "| __truncated__ ...

Let’s check the first and last page:

This looks the same as the beginning… how about the end?

Great! Our rural_urban object looks like it contains the entire Supplementary 3 table, as both the beginning and the end include the data we expected.

Data Wrangling

At this point we have large strings now for each page of the table, but this is not very convenient to work with. Now we will wrangle the data into a more usable form. Ideally we would like our data to be in some sort of tabular form.

Separate the data into lines

First it would be useful to separate each page into lines.

 chr [1:461] "                                                                          2                                    "| __truncated__ ...
[1] "Afghanistan          Women   20.6 (18.4-22.8)      20.1 (17.8-22.4)     23.2 (20.9-25.4) 24.4 (23.3-25.4)      23.6 (22.5-24.8)     26.3 (25.1-27.4)"

Removing excess white-space

We also have a lot of white-space… let’s get rid of the excess white spaces using str_squish().

[1] "2 2"                                                                                                                    
[2] "Age-standardised mean BMI in 1985 (kg/m ) Age-standardised mean BMI in 2017 (kg/m )"                                    
[3] "Country Sex"                                                                                                            
[4] "National Rural Urban National Rural Urban"                                                                              
[5] "Men 20.2 (17.8-22.7) 19.7 (17.2-22.2) 22.4 (20.0-25.0) 22.8 (20.3-25.3) 22.5 (20.0-25.0) 23.6 (21.0-26.1)"              
[6] "Afghanistan Women 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4)"

Now it is much easier to see the data.

If we look at the end of the first page of the table and the start of the second we can see that the header information is repeated, as well as a line with the page number and an empty line, and a line that says “2 2”.

 [1] "Benin Women 20.6 (19.1-22.0) 20.1 (18.5-21.6) 21.8 (20.3-23.3) 24.3 (23.5-25.0) 23.2 (22.5-24.0) 25.5 (24.7-26.3)"  
 [2] "Men 24.3 (21.8-26.8) na* 24.3 (21.8-26.8) 26.7 (24.3-29.2) na* 26.7 (24.3-29.2)"                                    
 [3] "Bermuda Women 25.4 (22.2-28.6) na* 25.4 (22.2-28.6) 28.5 (25.3-31.6) na* 28.5 (25.3-31.6)"                          
 [4] "Men 20.6 (19.1-22.1) 20.3 (18.7-21.8) 23.1 (21.5-24.6) 23.5 (22.8-24.3) 23.1 (22.2-23.9) 24.2 (23.3-25.2)"          
 [5] "Bhutan Women 20.7 (18.4-22.9) 20.3 (18.0-22.6) 23.0 (20.8-25.3) 24.6 (23.7-25.5) 23.8 (22.7-24.9) 25.9 (24.7-27.0)" 
 [6] "51"                                                                                                                 
 [7] ""                                                                                                                   
 [8] "2 2"                                                                                                                
 [9] "Age-standardised mean BMI in 1985 (kg/m ) Age-standardised mean BMI in 2017 (kg/m )"                                
[10] "Country Sex"                                                                                                        
[11] "National Rural Urban National Rural Urban"                                                                          
[12] "Men 23.3 (21.0-25.5) 22.9 (20.6-25.2) 23.6 (21.3-25.9) 26.1 (23.9-28.4) 25.3 (23.1-27.5) 26.5 (24.2-28.8)"          
[13] "Bolivia Women 23.8 (22.3-25.3) 23.0 (21.4-24.5) 24.6 (23.1-26.1) 27.9 (26.5-29.3) 27.0 (25.6-28.5) 28.3 (26.8-29.7)"

Although the header was necessary on all of the pages of the pdf version of the table, we only need that information once in our data.

Removing unnecessary repeated header information

So, let’s remove all the header information and the page number lines from the rural_urban object, then we will make a single line header for the beginning. One way to do this is to find all lines that include either “women” or “men” and only keep this data.

  [1]   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21
 [18]  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38
 [35]  39  40  41  42  43  44  45  46  47  48  55  56  57  58  59  60  61
 [52]  62  63  64  65  66  67  68  69  70  71  72  73  74  75  76  77  78
 [69]  79  80  81  82  83  84  85  86  87  88  89  90  91  92  93  94  95
 [86]  96  97  98 105 106 107 108 109 110 111 112 113 114 115 116 117 118
[103] 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
[120] 136 137 138 139 140 141 142 143 144 145 146 147 148 155 156 157 158
[137] 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
[154] 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
[171] 193 194 195 196 197 198 205 206 207 208 209 210 211 212 213 214 215
[188] 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
[205] 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 255
[222] 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
[239] 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
[256] 290 291 292 293 294 295 296 297 298 305 306 307 308 309 310 311 312
[273] 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
[290] 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
[307] 347 348 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
[324] 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
[341] 387 388 389 390 391 392 393 394 395 396 397 398 405 406 407 408 409
[358] 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
[375] 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443
[392] 444 445 446 447 448 455 456 457 458

OK, so this looks correct. This includes most lines but there are gaps where are header is located.

We can check our data now using either head() or glimpse().

 chr [1:400] "Men 20.2 (17.8-22.7) 19.7 (17.2-22.2) 22.4 (20.0-25.0) 22.8 (20.3-25.3) 22.5 (20.0-25.0) 23.6 (21.0-26.1)" ...
[1] "Men 20.2 (17.8-22.7) 19.7 (17.2-22.2) 22.4 (20.0-25.0) 22.8 (20.3-25.3) 22.5 (20.0-25.0) 23.6 (21.0-26.1)"              
[2] "Afghanistan Women 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4)"
[3] "Men 25.2 (23.9-26.5) 25.0 (23.7-26.4) 25.4 (24.0-26.7) 27.0 (26.0-27.9) 26.9 (25.9-27.9) 27.0 (26.0-28.0)"              
[4] "Albania Women 26.0 (24.1-27.9) 26.1 (24.1-28.1) 25.9 (23.9-27.8) 26.0 (24.8-27.2) 26.2 (24.8-27.5) 25.9 (24.6-27.2)"    
[5] "Men 22.1 (20.8-23.3) 21.8 (20.5-23.1) 22.3 (21.0-23.6) 25.1 (24.5-25.7) 24.8 (24.1-25.4) 25.2 (24.6-25.9)"              
[6] "Algeria Women 24.0 (22.2-25.7) 23.3 (21.4-25.1) 24.8 (22.9-26.6) 27.4 (26.7-28.0) 27.0 (26.3-27.8) 27.5 (26.7-28.2)"    

So the head() function shows us the first rows or lines of the data, while the glimpse() function provides us information about the total size of the object and shows us the first line or row.

Great! So now our data looks much better but we need to add back our header and we would like this to only be a single line to make it easy to transform our data into a table or table-like object.

Dealing with spacing

First let’s try splitting our header-less data into columns based on spaces:

      [,1]          [,2]    [,3]          [,4]          [,5]         
 [1,] "Men"         "20.2"  "(17.8-22.7)" "19.7"        "(17.2-22.2)"
 [2,] "Afghanistan" "Women" "20.6"        "(18.4-22.8)" "20.1"       
 [3,] "Men"         "25.2"  "(23.9-26.5)" "25.0"        "(23.7-26.4)"
 [4,] "Albania"     "Women" "26.0"        "(24.1-27.9)" "26.1"       
 [5,] "Men"         "22.1"  "(20.8-23.3)" "21.8"        "(20.5-23.1)"
 [6,] "Algeria"     "Women" "24.0"        "(22.2-25.7)" "23.3"       
 [7,] "Men"         "33.7"  "(32.7-34.7)" "32.6"        "(31.7-33.5)"
 [8,] "American"    "Samoa" "Women"       "34.3"        "(33.1-35.6)"
 [9,] "Men"         "25.0"  "(22.5-27.4)" "25.3"        "(22.8-27.7)"
[10,] "Andorra"     "Women" "25.2"        "(22.0-28.4)" "25.4"       
      [,6]          [,7]          [,8]          [,9]         
 [1,] "22.4"        "(20.0-25.0)" "22.8"        "(20.3-25.3)"
 [2,] "(17.8-22.4)" "23.2"        "(20.9-25.4)" "24.4"       
 [3,] "25.4"        "(24.0-26.7)" "27.0"        "(26.0-27.9)"
 [4,] "(24.1-28.1)" "25.9"        "(23.9-27.8)" "26.0"       
 [5,] "22.3"        "(21.0-23.6)" "25.1"        "(24.5-25.7)"
 [6,] "(21.4-25.1)" "24.8"        "(22.9-26.6)" "27.4"       
 [7,] "34.0"        "(32.9-35.1)" "34.3"        "(33.0-35.6)"
 [8,] "34.1"        "(33.0-35.2)" "34.4"        "(33.0-35.8)"
 [9,] "25.0"        "(22.5-27.4)" "26.8"        "(24.4-29.2)"
[10,] "(22.2-28.7)" "25.2"        "(22.0-28.4)" "25.3"       
      [,10]         [,11]         [,12]         [,13]        
 [1,] "22.5"        "(20.0-25.0)" "23.6"        "(21.0-26.1)"
 [2,] "(23.3-25.4)" "23.6"        "(22.5-24.8)" "26.3"       
 [3,] "26.9"        "(25.9-27.9)" "27.0"        "(26.0-28.0)"
 [4,] "(24.8-27.2)" "26.2"        "(24.8-27.5)" "25.9"       
 [5,] "24.8"        "(24.1-25.4)" "25.2"        "(24.6-25.9)"
 [6,] "(26.7-28.0)" "27.0"        "(26.3-27.8)" "27.5"       
 [7,] "34.6"        "(33.1-35.9)" "34.2"        "(32.9-35.6)"
 [8,] "35.3"        "(33.7-36.9)" "35.0"        "(33.1-36.9)"
 [9,] "26.8"        "(24.3-29.2)" "26.8"        "(24.3-29.3)"
[10,] "(22.1-28.6)" "25.2"        "(21.9-28.5)" "25.3"       
      [,14]         [,15]         [,16] [,17] [,18]
 [1,] ""            ""            ""    ""    ""   
 [2,] "(25.1-27.4)" ""            ""    ""    ""   
 [3,] ""            ""            ""    ""    ""   
 [4,] "(24.6-27.2)" ""            ""    ""    ""   
 [5,] ""            ""            ""    ""    ""   
 [6,] "(26.7-28.2)" ""            ""    ""    ""   
 [7,] ""            ""            ""    ""    ""   
 [8,] "35.4"        "(33.7-37.1)" ""    ""    ""   
 [9,] ""            ""            ""    ""    ""   
[10,] "(22.1-28.6)" ""            ""    ""    ""   

This almost worked, but unfortunately country names that have spaces will be a problem. We can see that American Samoa has been divided into two columns and all subsequent columns are shifted.

So now let’s try to extract the country information, by separating the country information from the sex information when the sex is female. Sex always starts with either a capital “W” if the gender is female. We need to use a space before the “W” otherwise we will split some of the country names if the names starts with “W”. Here we will also introduce the concept of piping, which uses the %>%. This is really useful when we have multiple steps, which we will show soon.

[1] "Afghanistan"                                                                                               
[2] "omen 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4)"
[3] "Albania"                                                                                                   
[4] "omen 26.0 (24.1-27.9) 26.1 (24.1-28.1) 25.9 (23.9-27.8) 26.0 (24.8-27.2) 26.2 (24.8-27.5) 25.9 (24.6-27.2)"
[5] "Algeria"                                                                                                   
[6] "omen 24.0 (22.2-25.7) 23.3 (21.4-25.1) 24.8 (22.9-26.6) 27.4 (26.7-28.0) 27.0 (26.3-27.8) 27.5 (26.7-28.2)"

Now we can see that Country is always the odd rows and the rest of the data is the rest of the rows

We can take a look to make sure that all the country names look as expected:

                       country_split
1                        Afghanistan
2                            Albania
3                            Algeria
4                     American Samoa
5                            Andorra
6                             Angola
7                Antigua and Barbuda
8                          Argentina
9                            Armenia
10                         Australia
11                           Austria
12                        Azerbaijan
13                           Bahamas
14                           Bahrain
15                        Bangladesh
16                          Barbados
17                           Belarus
18                           Belgium
19                            Belize
20                             Benin
21                           Bermuda
22                            Bhutan
23                           Bolivia
24            Bosnia and Herzegovina
25                          Botswana
26                            Brazil
27                 Brunei Darussalam
28                          Bulgaria
29                      Burkina Faso
30                           Burundi
31                        Cabo Verde
32                          Cambodia
33                          Cameroon
34                            Canada
35          Central African Republic
36                              Chad
37                             Chile
38                             China
39             China (Hong Kong SAR)
40                          Colombia
41                           Comoros
42                             Congo
43                      Cook Islands
44                        Costa Rica
45                     Cote d'Ivoire
46                           Croatia
47                              Cuba
48                            Cyprus
49                    Czech Republic
50                           Denmark
51                          Djibouti
52                          Dominica
53                Dominican Republic
54                          DR Congo
55                           Ecuador
56                             Egypt
57                       El Salvador
58                 Equatorial Guinea
59                           Eritrea
60                           Estonia
61                          Ethiopia
62                              Fiji
63                           Finland
64                            France
65                  French Polynesia
66                             Gabon
67                            Gambia
68                           Georgia
69                           Germany
70                             Ghana
71                            Greece
72                         Greenland
73                           Grenada
74                         Guatemala
75                            Guinea
76                     Guinea Bissau
77                            Guyana
78                             Haiti
79                          Honduras
80                           Hungary
81                           Iceland
82                             India
83                         Indonesia
84                              Iran
85                              Iraq
86                           Ireland
87                            Israel
88                             Italy
89                           Jamaica
90                             Japan
91                            Jordan
92                        Kazakhstan
93                             Kenya
94                          Kiribati
95                            Kuwait
96                        Kyrgyzstan
97                           Lao PDR
98                            Latvia
99                           Lebanon
100                          Lesotho
101                          Liberia
102                            Libya
103                        Lithuania
104                       Luxembourg
105                 Macedonia (TFYR)
106                       Madagascar
107                           Malawi
108                         Malaysia
109                         Maldives
110                             Mali
111                            Malta
112                 Marshall Islands
113                       Mauritania
114                        Mauritius
115                           Mexico
116 Micronesia (Federated States of)
117                          Moldova
118                         Mongolia
119                       Montenegro
120                          Morocco
121                       Mozambique
122                          Myanmar
123                          Namibia
124                            Nauru
125                            Nepal
126                      Netherlands
127                      New Zealand
128                        Nicaragua
129                            Niger
130                          Nigeria
131                             Niue
132                      North Korea
133                           Norway
134   Occupied Palestinian Territory
135                             Oman
136                         Pakistan
137                            Palau
138                           Panama
139                 Papua New Guinea
140                         Paraguay
141                             Peru
142                      Philippines
143                           Poland
144                         Portugal
145                      Puerto Rico
146                            Qatar
147                          Romania
148               Russian Federation
149                           Rwanda
150            Saint Kitts and Nevis
151                      Saint Lucia
152 Saint Vincent and the Grenadines
153                            Samoa
154            Sao Tome and Principe
155                     Saudi Arabia
156                          Senegal
157                           Serbia
158                       Seychelles
159                     Sierra Leone
160                        Singapore
161                         Slovakia
162                         Slovenia
163                  Solomon Islands
164                          Somalia
165                     South Africa
166                      South Korea
167                            Spain
168                        Sri Lanka
169                   Sudan (former)
170                         Suriname
171                        Swaziland
172                           Sweden
173                      Switzerland
174             Syrian Arab Republic
175                           Taiwan
176                       Tajikistan
177                         Tanzania
178                         Thailand
179                      Timor-Leste
180                             Togo
181                          Tokelau
182                            Tonga
183              Trinidad and Tobago
184                          Tunisia
185                           Turkey
186                     Turkmenistan
187                           Tuvalu
188                           Uganda
189                          Ukraine
190             United Arab Emirates
191                   United Kingdom
192         United States of America
193                          Uruguay
194                       Uzbekistan
195                          Vanuatu
196                        Venezuela
197                         Viet Nam
198                            Yemen
199                           Zambia
200                         Zimbabwe

Great! Now we have a list of the countries that can be used for both the male and female data.

Let’s add the “W” back to our Women data. We can do so by replacing the string “omen” with “Women” using str_repace().

 chr [1:200] "Afghanistan Women 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4)" ...
[1] "Women 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4)"
[2] "Women 26.0 (24.1-27.9) 26.1 (24.1-28.1) 25.9 (23.9-27.8) 26.0 (24.8-27.2) 26.2 (24.8-27.5) 25.9 (24.6-27.2)"
[3] "Women 24.0 (22.2-25.7) 23.3 (21.4-25.1) 24.8 (22.9-26.6) 27.4 (26.7-28.0) 27.0 (26.3-27.8) 27.5 (26.7-28.2)"
[4] "Women 34.3 (33.1-35.6) 34.1 (33.0-35.2) 34.4 (33.0-35.8) 35.3 (33.7-36.9) 35.0 (33.1-36.9) 35.4 (33.7-37.1)"
[5] "Women 25.2 (22.0-28.4) 25.4 (22.2-28.7) 25.2 (22.0-28.4) 25.3 (22.1-28.6) 25.2 (21.9-28.5) 25.3 (22.1-28.6)"
[6] "Women 21.3 (18.0-24.6) 20.9 (17.6-24.3) 22.7 (19.3-26.0) 24.4 (21.2-27.7) 23.3 (20.0-26.7) 25.7 (22.4-29.1)"

It’s always a good idea to check that your data objects are the size you expect when wrangling. We can do so with the dim() function, which shows us the dimensions of data objects.

[1] 200   1

Great! There are 200 rows like we expected.

Let’s grab the male data:

[1] Men 20.2 (17.8-22.7) 19.7 (17.2-22.2) 22.4 (20.0-25.0) 22.8 (20.3-25.3) 22.5 (20.0-25.0) 23.6 (21.0-26.1)
[2] Men 25.2 (23.9-26.5) 25.0 (23.7-26.4) 25.4 (24.0-26.7) 27.0 (26.0-27.9) 26.9 (25.9-27.9) 27.0 (26.0-28.0)
[3] Men 22.1 (20.8-23.3) 21.8 (20.5-23.1) 22.3 (21.0-23.6) 25.1 (24.5-25.7) 24.8 (24.1-25.4) 25.2 (24.6-25.9)
[4] Men 33.7 (32.7-34.7) 32.6 (31.7-33.5) 34.0 (32.9-35.1) 34.3 (33.0-35.6) 34.6 (33.1-35.9) 34.2 (32.9-35.6)
[5] Men 25.0 (22.5-27.4) 25.3 (22.8-27.7) 25.0 (22.5-27.4) 26.8 (24.4-29.2) 26.8 (24.3-29.2) 26.8 (24.3-29.3)
[6] Men 20.5 (17.9-23.1) 20.2 (17.6-22.9) 21.4 (18.8-24.0) 22.6 (20.0-25.1) 22.0 (19.4-24.6) 23.2 (20.6-25.9)
400 Levels: Afghanistan Women 20.6 (18.4-22.8) 20.1 (17.8-22.4) 23.2 (20.9-25.4) 24.4 (23.3-25.4) 23.6 (22.5-24.8) 26.3 (25.1-27.4) ...
[1] 200   1

How about our number of columns?

If we try splitting our data by space again, will it have the expected number of columns? What about the rows that contain na* values?

# A tibble: 5 x 12
  V1    V2    V3     V4    V5     V6    V7    V8    V9    V10   V11   V12  
  <chr> <chr> <chr>  <chr> <chr>  <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 Men   24.3  (21.8… na*   24.3   (21.… 26.7  (24.… na*   26.7  (24.… ""   
2 Men   22.4  (21.4… 21.5  (20.2… 22.4  (21.… 24.8  (23.… na*   24.8  (23.…
3 Men   32.6  (32.0… na*   32.6   (32.… 32.9  (31.… na*   32.9  (31.… ""   
4 Men   22.8  (22.2… na*   22.8   (22.… 24.4  (23.… na*   24.4  (23.… ""   
5 Men   29.6  (28.1… 29.6  (28.1… na*   32.3  (31.… 32.3  (31.… na*   ""   

Dealing with NA values

So close! Notice that the "na*" values have shifted the subsequent values within the columns because typically there is a space between the BMI and the credible intervals. Here we can see this data in our original pdf:

We need to replace our na* values with something that includes a space so that when we separate our data by space we will have two values instead of one when we have an na* . Therefore, na* na* should work.

[1] "factor"
 [1] "Men 20.7 (19.4-22.1) 20.3 (18.9-21.7) 21.7 (20.3-23.1) 22.7 (22.0-23.3) 22.1 (21.3-22.8) 23.4 (22.7-24.1)"
 [2] "Men 24.3 (21.8-26.8) na* na* 24.3 (21.8-26.8) 26.7 (24.3-29.2) na* na* 26.7 (24.3-29.2)"                  
 [3] "Men 20.6 (19.1-22.1) 20.3 (18.7-21.8) 23.1 (21.5-24.6) 23.5 (22.8-24.3) 23.1 (22.2-23.9) 24.2 (23.3-25.2)"
 [4] "Men 23.3 (21.0-25.5) 22.9 (20.6-25.2) 23.6 (21.3-25.9) 26.1 (23.9-28.4) 25.3 (23.1-27.5) 26.5 (24.2-28.8)"
 [5] "Men 24.9 (23.5-26.2) 24.8 (23.4-26.2) 25.0 (23.6-26.4) 26.8 (25.7-27.8) 26.7 (25.7-27.8) 26.8 (25.7-27.9)"
 [6] "Men 20.6 (19.2-22.0) 20.3 (18.8-21.7) 21.4 (20.0-22.9) 22.6 (21.9-23.4) 21.9 (20.9-22.8) 23.2 (22.3-24.0)"
 [7] "Men 23.3 (22.5-24.0) 22.2 (21.4-23.0) 23.7 (22.9-24.5) 26.2 (25.7-26.7) 25.0 (24.3-25.6) 26.4 (25.9-26.9)"
 [8] "Men 24.0 (22.5-25.4) 23.7 (22.1-25.1) 24.2 (22.7-25.7) 27.1 (26.4-27.7) 26.6 (26.0-27.3) 27.2 (26.5-27.9)"
 [9] "Men 25.0 (23.8-26.4) 24.9 (23.5-26.4) 25.1 (23.8-26.5) 27.0 (25.8-28.1) 27.0 (25.7-28.3) 27.0 (25.7-28.2)"
[10] "Men 20.2 (18.8-21.5) 20.0 (18.6-21.4) 21.4 (19.9-22.9) 22.2 (21.4-23.0) 21.8 (21.0-22.6) 23.1 (22.1-24.1)"
[11] "Men 20.2 (17.7-22.6) 20.1 (17.6-22.5) 21.2 (18.7-23.6) 22.1 (19.8-24.5) 22.0 (19.6-24.3) 23.2 (20.8-25.6)"
[1] "character"
 [1] "Women 20.6 (19.1-22.0) 20.1 (18.5-21.6) 21.8 (20.3-23.3) 24.3 (23.5-25.0) 23.2 (22.5-24.0) 25.5 (24.7-26.3)"
 [2] "Women 25.4 (22.2-28.6) na* na* 25.4 (22.2-28.6) 28.5 (25.3-31.6) na* na* 28.5 (25.3-31.6)"                  
 [3] "Women 20.7 (18.4-22.9) 20.3 (18.0-22.6) 23.0 (20.8-25.3) 24.6 (23.7-25.5) 23.8 (22.7-24.9) 25.9 (24.7-27.0)"
 [4] "Women 23.8 (22.3-25.3) 23.0 (21.4-24.5) 24.6 (23.1-26.1) 27.9 (26.5-29.3) 27.0 (25.6-28.5) 28.3 (26.8-29.7)"
 [5] "Women 25.5 (23.5-27.4) 25.7 (23.7-27.7) 25.1 (23.1-27.0) 25.7 (24.4-27.1) 26.0 (24.6-27.5) 25.3 (23.9-26.8)"
 [6] "Women 24.2 (22.2-26.2) 23.7 (21.5-25.8) 25.6 (23.5-27.7) 26.2 (25.3-27.1) 25.0 (23.8-26.2) 27.0 (26.0-28.2)"
 [7] "Women 24.0 (23.2-25.0) 23.1 (22.1-24.1) 24.4 (23.5-25.4) 26.9 (26.2-27.5) 26.4 (25.7-27.2) 26.9 (26.3-27.6)"
 [8] "Women 23.6 (21.4-25.6) 22.9 (20.7-25.0) 24.0 (21.8-26.1) 27.4 (26.6-28.1) 27.0 (26.1-27.8) 27.5 (26.7-28.2)"
 [9] "Women 25.2 (23.4-27.1) 25.5 (23.4-27.6) 25.0 (23.1-26.9) 25.6 (24.1-27.1) 26.0 (24.2-27.8) 25.5 (23.9-27.1)"
[10] "Women 19.9 (18.7-21.2) 19.6 (18.4-20.9) 22.0 (20.7-23.3) 22.2 (21.4-23.1) 21.1 (20.2-22.0) 24.7 (23.7-25.7)"
[11] "Women 19.6 (17.5-21.7) 19.5 (17.4-21.6) 21.7 (19.5-23.8) 21.1 (20.3-22.0) 20.7 (19.8-21.6) 24.0 (23.0-24.9)"

Great, now we can split our data by spaces.

Splitting the data

# A tibble: 6 x 13
  V1    V2    V3     V4    V5     V6    V7    V8    V9    V10   V11   V12  
  <chr> <chr> <chr>  <chr> <chr>  <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 Men   20.2  (17.8… 19.7  (17.2… 22.4  (20.… 22.8  (20.… 22.5  (20.… 23.6 
2 Men   25.2  (23.9… 25.0  (23.7… 25.4  (24.… 27.0  (26.… 26.9  (25.… 27.0 
3 Men   22.1  (20.8… 21.8  (20.5… 22.3  (21.… 25.1  (24.… 24.8  (24.… 25.2 
4 Men   33.7  (32.7… 32.6  (31.7… 34.0  (32.… 34.3  (33.… 34.6  (33.… 34.2 
5 Men   25.0  (22.5… 25.3  (22.8… 25.0  (22.… 26.8  (24.… 26.8  (24.… 26.8 
6 Men   20.5  (17.9… 20.2  (17.6… 21.4  (18.… 22.6  (20.… 22.0  (19.… 23.2 
# … with 1 more variable: V13 <chr>
# A tibble: 6 x 13
  V1    V2    V3     V4    V5     V6    V7    V8    V9    V10   V11   V12  
  <chr> <chr> <chr>  <chr> <chr>  <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 Women 20.6  (18.4… 20.1  (17.8… 23.2  (20.… 24.4  (23.… 23.6  (22.… 26.3 
2 Women 26.0  (24.1… 26.1  (24.1… 25.9  (23.… 26.0  (24.… 26.2  (24.… 25.9 
3 Women 24.0  (22.2… 23.3  (21.4… 24.8  (22.… 27.4  (26.… 27.0  (26.… 27.5 
4 Women 34.3  (33.1… 34.1  (33.0… 34.4  (33.… 35.3  (33.… 35.0  (33.… 35.4 
5 Women 25.2  (22.0… 25.4  (22.2… 25.2  (22.… 25.3  (22.… 25.2  (21.… 25.3 
6 Women 21.3  (18.0… 20.9  (17.6… 22.7  (19.… 24.4  (21.… 23.3  (20.… 25.7 
# … with 1 more variable: V13 <chr>
# A tibble: 11 x 13
   V1    V2    V3     V4    V5    V6    V7    V8    V9    V10   V11   V12  
   <chr> <chr> <chr>  <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 Women 20.6  (19.1… 20.1  (18.… 21.8  (20.… 24.3  (23.… 23.2  (22.… 25.5 
 2 Women 25.4  (22.2… na*   na*   25.4  (22.… 28.5  (25.… na*   na*   28.5 
 3 Women 20.7  (18.4… 20.3  (18.… 23.0  (20.… 24.6  (23.… 23.8  (22.… 25.9 
 4 Women 23.8  (22.3… 23.0  (21.… 24.6  (23.… 27.9  (26.… 27.0  (25.… 28.3 
 5 Women 25.5  (23.5… 25.7  (23.… 25.1  (23.… 25.7  (24.… 26.0  (24.… 25.3 
 6 Women 24.2  (22.2… 23.7  (21.… 25.6  (23.… 26.2  (25.… 25.0  (23.… 27.0 
 7 Women 24.0  (23.2… 23.1  (22.… 24.4  (23.… 26.9  (26.… 26.4  (25.… 26.9 
 8 Women 23.6  (21.4… 22.9  (20.… 24.0  (21.… 27.4  (26.… 27.0  (26.… 27.5 
 9 Women 25.2  (23.4… 25.5  (23.… 25.0  (23.… 25.6  (24.… 26.0  (24.… 25.5 
10 Women 19.9  (18.7… 19.6  (18.… 22.0  (20.… 22.2  (21.… 21.1  (20.… 24.7 
11 Women 19.6  (17.5… 19.5  (17.… 21.7  (19.… 21.1  (20.… 20.7  (19.… 24.0 
# … with 1 more variable: V13 <chr>

Adding new header

We can see from our pdf and our object called header what the header was like. Let’s also make a new single line header, but let’s wait to add Country:

Let’s change the names of our columns of our tibble to this new header for our Men and Women data

Now we will add our country data to both our Men and Women tibbles:

   country_split   Sex National_BMI_1985 National_BMI_1985_CI
1    Afghanistan Women              20.6          (18.4-22.8)
2        Albania Women              26.0          (24.1-27.9)
3        Algeria Women              24.0          (22.2-25.7)
4 American Samoa Women              34.3          (33.1-35.6)
5        Andorra Women              25.2          (22.0-28.4)
6         Angola Women              21.3          (18.0-24.6)
  Rural_BMI_1985 Rural_BMI_1985_CI Urban_BMI_1985 Urban_BMI_1985_CI
1           20.1       (17.8-22.4)           23.2       (20.9-25.4)
2           26.1       (24.1-28.1)           25.9       (23.9-27.8)
3           23.3       (21.4-25.1)           24.8       (22.9-26.6)
4           34.1       (33.0-35.2)           34.4       (33.0-35.8)
5           25.4       (22.2-28.7)           25.2       (22.0-28.4)
6           20.9       (17.6-24.3)           22.7       (19.3-26.0)
  National_BMI_2017 National_BMI_2017_CI Rural_BMI_2017 Rural_BMI_2017_CI
1              24.4          (23.3-25.4)           23.6       (22.5-24.8)
2              26.0          (24.8-27.2)           26.2       (24.8-27.5)
3              27.4          (26.7-28.0)           27.0       (26.3-27.8)
4              35.3          (33.7-36.9)           35.0       (33.1-36.9)
5              25.3          (22.1-28.6)           25.2       (21.9-28.5)
6              24.4          (21.2-27.7)           23.3       (20.0-26.7)
  Urban_BMI_2017 Urban_BMI_2017_CI
1           26.3       (25.1-27.4)
2           25.9       (24.6-27.2)
3           27.5       (26.7-28.2)
4           35.4       (33.7-37.1)
5           25.3       (22.1-28.6)
6           25.7       (22.4-29.1)

Changing variable names

Here we will change the variable name of the country data to country, currently it is called country_split. Here we will also introduce the concept of the assignment pipe. In this case our pipe operator looks like this %<>% . Using this fancier pipe requires another package, called magrittr. The other simpler pipe options from this package are loaded with tidyverse (if you used library(tidyverse) which loads most tidyverse packages), but not this fancier version.

The > portion of the pipe still behaves like a normal pipe, while the < portion of the pipe makes an assignment to whatever the <is pointing to, just like when we use the typical assignment operator <-.

Joining the data

Now we can combine our Men and Women data using the full_join() function of dplyr. This will put all the female data first (x) and all the male data second (y).

'data.frame':   400 obs. of  14 variables:
 $ Country             : Factor w/ 400 levels "Afghanistan",..: 1 2 3 4 5 6 7 8 9 10 ...
 $ Sex                 : chr  "Men" "Men" "Men" "Men" ...
 $ National_BMI_1985   : chr  "20.2" "25.2" "22.1" "33.7" ...
 $ National_BMI_1985_CI: chr  "(17.8-22.7)" "(23.9-26.5)" "(20.8-23.3)" "(32.7-34.7)" ...
 $ Rural_BMI_1985      : chr  "19.7" "25.0" "21.8" "32.6" ...
 $ Rural_BMI_1985_CI   : chr  "(17.2-22.2)" "(23.7-26.4)" "(20.5-23.1)" "(31.7-33.5)" ...
 $ Urban_BMI_1985      : chr  "22.4" "25.4" "22.3" "34.0" ...
 $ Urban_BMI_1985_CI   : chr  "(20.0-25.0)" "(24.0-26.7)" "(21.0-23.6)" "(32.9-35.1)" ...
 $ National_BMI_2017   : chr  "22.8" "27.0" "25.1" "34.3" ...
 $ National_BMI_2017_CI: chr  "(20.3-25.3)" "(26.0-27.9)" "(24.5-25.7)" "(33.0-35.6)" ...
 $ Rural_BMI_2017      : chr  "22.5" "26.9" "24.8" "34.6" ...
 $ Rural_BMI_2017_CI   : chr  "(20.0-25.0)" "(25.9-27.9)" "(24.1-25.4)" "(33.1-35.9)" ...
 $ Urban_BMI_2017      : chr  "23.6" "27.0" "25.2" "34.2" ...
 $ Urban_BMI_2017_CI   : chr  "(21.0-26.1)" "(26.0-28.0)" "(24.6-25.9)" "(32.9-35.6)" ...

Sorting the data

Now Lets sort the data by country:

      Country   Sex National_BMI_1985 National_BMI_1985_CI Rural_BMI_1985
1 Afghanistan   Men              20.2          (17.8-22.7)           19.7
2 Afghanistan Women              20.6          (18.4-22.8)           20.1
3     Albania   Men              25.2          (23.9-26.5)           25.0
4     Albania Women              26.0          (24.1-27.9)           26.1
5     Algeria   Men              22.1          (20.8-23.3)           21.8
6     Algeria Women              24.0          (22.2-25.7)           23.3
  Rural_BMI_1985_CI Urban_BMI_1985 Urban_BMI_1985_CI National_BMI_2017
1       (17.2-22.2)           22.4       (20.0-25.0)              22.8
2       (17.8-22.4)           23.2       (20.9-25.4)              24.4
3       (23.7-26.4)           25.4       (24.0-26.7)              27.0
4       (24.1-28.1)           25.9       (23.9-27.8)              26.0
5       (20.5-23.1)           22.3       (21.0-23.6)              25.1
6       (21.4-25.1)           24.8       (22.9-26.6)              27.4
  National_BMI_2017_CI Rural_BMI_2017 Rural_BMI_2017_CI Urban_BMI_2017
1          (20.3-25.3)           22.5       (20.0-25.0)           23.6
2          (23.3-25.4)           23.6       (22.5-24.8)           26.3
3          (26.0-27.9)           26.9       (25.9-27.9)           27.0
4          (24.8-27.2)           26.2       (24.8-27.5)           25.9
5          (24.5-25.7)           24.8       (24.1-25.4)           25.2
6          (26.7-28.0)           27.0       (26.3-27.8)           27.5
  Urban_BMI_2017_CI
1       (21.0-26.1)
2       (25.1-27.4)
3       (26.0-28.0)
4       (24.6-27.2)
5       (24.6-25.9)
6       (26.7-28.2)

Our data is looking great! Now we might want to make sure that our observations for each variable look the way we want. In other words if we want to make plots about National BMI in 1985 then we would need our values to be numeric. Looking at our BMI data using str(), we can see the type of data for each of our variables listed just after variable name and the “:” colon. Looks like none of our BMI data is actually numeric, but of the class character. Let’s change that now.

'data.frame':   400 obs. of  14 variables:
 $ Country             : Factor w/ 400 levels "Afghanistan",..: 1 1 2 2 3 3 4 4 5 5 ...
 $ Sex                 : chr  "Men" "Women" "Men" "Women" ...
 $ National_BMI_1985   : chr  "20.2" "20.6" "25.2" "26.0" ...
 $ National_BMI_1985_CI: chr  "(17.8-22.7)" "(18.4-22.8)" "(23.9-26.5)" "(24.1-27.9)" ...
 $ Rural_BMI_1985      : chr  "19.7" "20.1" "25.0" "26.1" ...
 $ Rural_BMI_1985_CI   : chr  "(17.2-22.2)" "(17.8-22.4)" "(23.7-26.4)" "(24.1-28.1)" ...
 $ Urban_BMI_1985      : chr  "22.4" "23.2" "25.4" "25.9" ...
 $ Urban_BMI_1985_CI   : chr  "(20.0-25.0)" "(20.9-25.4)" "(24.0-26.7)" "(23.9-27.8)" ...
 $ National_BMI_2017   : chr  "22.8" "24.4" "27.0" "26.0" ...
 $ National_BMI_2017_CI: chr  "(20.3-25.3)" "(23.3-25.4)" "(26.0-27.9)" "(24.8-27.2)" ...
 $ Rural_BMI_2017      : chr  "22.5" "23.6" "26.9" "26.2" ...
 $ Rural_BMI_2017_CI   : chr  "(20.0-25.0)" "(22.5-24.8)" "(25.9-27.9)" "(24.8-27.5)" ...
 $ Urban_BMI_2017      : chr  "23.6" "26.3" "27.0" "25.9" ...
 $ Urban_BMI_2017_CI   : chr  "(21.0-26.1)" "(25.1-27.4)" "(26.0-28.0)" "(24.6-27.2)" ...

We could change these values to be numeric with 6 lines of code like this:

'data.frame':   400 obs. of  14 variables:
 $ Country             : Factor w/ 400 levels "Afghanistan",..: 1 1 2 2 3 3 4 4 5 5 ...
 $ Sex                 : chr  "Men" "Women" "Men" "Women" ...
 $ National_BMI_1985   : num  20.2 20.6 25.2 26 22.1 24 33.7 34.3 25 25.2 ...
 $ National_BMI_1985_CI: chr  "(17.8-22.7)" "(18.4-22.8)" "(23.9-26.5)" "(24.1-27.9)" ...
 $ Rural_BMI_1985      : num  19.7 20.1 25 26.1 21.8 23.3 32.6 34.1 25.3 25.4 ...
 $ Rural_BMI_1985_CI   : chr  "(17.2-22.2)" "(17.8-22.4)" "(23.7-26.4)" "(24.1-28.1)" ...
 $ Urban_BMI_1985      : num  22.4 23.2 25.4 25.9 22.3 24.8 34 34.4 25 25.2 ...
 $ Urban_BMI_1985_CI   : chr  "(20.0-25.0)" "(20.9-25.4)" "(24.0-26.7)" "(23.9-27.8)" ...
 $ National_BMI_2017   : num  22.8 24.4 27 26 25.1 27.4 34.3 35.3 26.8 25.3 ...
 $ National_BMI_2017_CI: chr  "(20.3-25.3)" "(23.3-25.4)" "(26.0-27.9)" "(24.8-27.2)" ...
 $ Rural_BMI_2017      : num  22.5 23.6 26.9 26.2 24.8 27 34.6 35 26.8 25.2 ...
 $ Rural_BMI_2017_CI   : chr  "(20.0-25.0)" "(22.5-24.8)" "(25.9-27.9)" "(24.8-27.5)" ...
 $ Urban_BMI_2017      : num  23.6 26.3 27 25.9 25.2 27.5 34.2 35.4 26.8 25.3 ...
 $ Urban_BMI_2017_CI   : chr  "(21.0-26.1)" "(25.1-27.4)" "(26.0-28.0)" "(24.6-27.2)" ...

Or we can use a more automated way with the map() function of the purrr package:

# A tibble: 6 x 8
  National_BMI_19… Rural_BMI_1985 Urban_BMI_1985 National_BMI_20…
             <dbl>          <dbl>          <dbl>            <dbl>
1             20.2           19.7           22.4             22.8
2             20.6           20.1           23.2             24.4
3             25.2           25             25.4             27  
4             26             26.1           25.9             26  
5             22.1           21.8           22.3             25.1
6             24             23.3           24.8             27.4
# … with 4 more variables: Rural_BMI_2017 <dbl>, Urban_BMI_2017 <dbl>,
#   Country <fct>, Sex <chr>

It is generally useful to get the data in what is called long format for other analyses, and particularly for plotting.

For a more detailed description about this, please see this case study

To do this we will use the gather() function of the tidyr package:

# A tibble: 6 x 4
  Country     Sex   class_BMI           BMI
  <fct>       <chr> <chr>             <dbl>
1 Afghanistan Men   National_BMI_1985  20.2
2 Afghanistan Women National_BMI_1985  20.6
3 Albania     Men   National_BMI_1985  25.2
4 Albania     Women National_BMI_1985  26  
5 Algeria     Men   National_BMI_1985  22.1
6 Algeria     Women National_BMI_1985  24  

It would be useful to parse the 1985 and the 2017 data. We can do so by separating the parts of the class_BMI column using the separate() function of the tidyr package.

# A tibble: 6 x 5
  Country     Sex   Region   Year    BMI
  <fct>       <chr> <chr>    <chr> <dbl>
1 Afghanistan Men   National 1985   20.2
2 Afghanistan Women National 1985   20.6
3 Albania     Men   National 1985   25.2
4 Albania     Women National 1985   26  
5 Algeria     Men   National 1985   22.1
6 Algeria     Women National 1985   24  
[1] 400   8
[1] 2400    5

Great! our data is very usable now in this format!

Data Exploration

Now that our data is clean and in a format that we can work with, we can start to take a look at the data and how different groups might compare.

Statistically speaking there are tests that can allow us to evaluate if the means of the groups are different. First let’s see how our data looks in general.

General summary

 National_BMI_1985 Rural_BMI_1985 Urban_BMI_1985  National_BMI_2017
 Min.   :18.20     Min.   :17.7   Min.   :19.30   Min.   :20.20    
 1st Qu.:21.50     1st Qu.:20.9   1st Qu.:22.43   1st Qu.:24.07    
 Median :24.00     Median :23.4   Median :24.30   Median :26.15    
 Mean   :23.68     Mean   :23.3   Mean   :24.24   Mean   :26.00    
 3rd Qu.:25.23     3rd Qu.:25.1   3rd Qu.:25.40   3rd Qu.:27.43    
 Max.   :34.30     Max.   :34.1   Max.   :34.40   Max.   :35.30    
                   NA's   :6      NA's   :2                        
 Rural_BMI_2017  Urban_BMI_2017            Country        Sex           
 Min.   :19.80   Min.   :21.50   Afghanistan   :  2   Length:400        
 1st Qu.:23.30   1st Qu.:24.80   Albania       :  2   Class :character  
 Median :26.00   Median :26.30   Algeria       :  2   Mode  :character  
 Mean   :25.61   Mean   :26.37   American Samoa:  2                     
 3rd Qu.:27.30   3rd Qu.:27.60   Andorra       :  2                     
 Max.   :35.00   Max.   :35.40   Angola        :  2                     
 NA's   :8       NA's   :2       (Other)       :388                     

Lets look at the Data separately by gender:

 National_BMI_1985 Rural_BMI_1985  Urban_BMI_1985  National_BMI_2017
 Min.   :18.20     Min.   :17.70   Min.   :19.70   Min.   :21.00    
 1st Qu.:22.00     1st Qu.:21.20   1st Qu.:22.85   1st Qu.:24.40    
 Median :24.25     Median :23.90   Median :24.60   Median :26.10    
 Mean   :24.00     Mean   :23.59   Mean   :24.63   Mean   :26.38    
 3rd Qu.:25.50     3rd Qu.:25.40   3rd Qu.:25.60   3rd Qu.:28.00    
 Max.   :34.30     Max.   :34.10   Max.   :34.40   Max.   :35.30    
                   NA's   :3       NA's   :1                        
 Rural_BMI_2017  Urban_BMI_2017            Country        Sex           
 Min.   :20.40   Min.   :21.60   Afghanistan   :  1   Length:200        
 1st Qu.:23.70   1st Qu.:25.30   Albania       :  1   Class :character  
 Median :26.20   Median :26.40   Algeria       :  1   Mode  :character  
 Mean   :25.98   Mean   :26.84   American Samoa:  1                     
 3rd Qu.:27.60   3rd Qu.:28.25   Andorra       :  1                     
 Max.   :35.00   Max.   :35.40   Angola        :  1                     
 NA's   :4       NA's   :1       (Other)       :194                     
 National_BMI_1985 Rural_BMI_1985  Urban_BMI_1985  National_BMI_2017
 Min.   :18.50     Min.   :18.40   Min.   :19.30   Min.   :20.20    
 1st Qu.:21.10     1st Qu.:20.80   1st Qu.:22.10   1st Qu.:23.30    
 Median :23.60     Median :23.20   Median :24.10   Median :26.20    
 Mean   :23.36     Mean   :23.01   Mean   :23.84   Mean   :25.61    
 3rd Qu.:25.00     3rd Qu.:24.90   3rd Qu.:25.10   3rd Qu.:27.10    
 Max.   :33.70     Max.   :32.60   Max.   :34.00   Max.   :34.30    
                   NA's   :3       NA's   :1                        
 Rural_BMI_2017  Urban_BMI_2017           Country        Sex           
 Min.   :19.80   Min.   :21.5   Afghanistan   :  1   Length:200        
 1st Qu.:22.60   1st Qu.:23.8   Albania       :  1   Class :character  
 Median :25.75   Median :26.3   Algeria       :  1   Mode  :character  
 Mean   :25.24   Mean   :25.9   American Samoa:  1                     
 3rd Qu.:27.00   3rd Qu.:27.2   Andorra       :  1                     
 Max.   :34.60   Max.   :34.2   Angola        :  1                     
 NA's   :4       NA's   :1      (Other)       :194                     

It looks like mean BMIs have increased in all regions for both men and women. It is unclear though if this change is statistically significant.

Distributions

In order to apply a statistical test to compare the means, one of the first things that is useful to do is to plot the frequency of the different possible values. This is called a distribution. To do this we can use the hist() function to create a histogram.

If the data were what we call normally distributed then the distribution should be equally centered around the mean and would look something like this:

# A tibble: 6 x 1
  norm_data
      <dbl>
1      25.0
2      24.9
3      22.8
4      23.3
5      22.0
6      24.1

Alternatively we can plot this using the geom_hist() function of the ggplot2 package. The ggplot2 package creates plots by using layers. Notice in the following code how their is a plus sign between the ggplot() function and the geom_histogram() function. With ggplot2 we select what data we would like to plot using the first function (ggplot()) and then we add on additional layers of complexity. In this case the geom_histrogram() function initiates the plotting of a histogram with the data that was identified in the ggplot() function. We will see later how we can add many layers to plots with ggplot2. For additional information on using ggplot2, see this case study.

Let’s see how our data looks:

OK, so the data looks like it is what we call right skewed because the tail of the distribution is longer on the right side, but it looks fairly normally distributed.

If we parse our data, what does it look like? The easiest way to do this is to use some other functions of the ggplot2 package, particularly the facet_wrap() function, which will allow us to look at differences in the distribution of the BMI data by year, gender, and region. We can sequentially divide our plots by deeper levels using multiple variables and the + plus sign within facet_wrap().

### Quantile Quantile Plots

Let’s use a method called quantile quantile plotting to determine if the data is indeed normally distributed. These plots are called QQ plots. This method allows us to test the fit of known theoretical distributions (like the normal distribution) with our observed distribution. To do this we will plot the quantiles of our data on the y-axis and the quantiles of the theoretical normal distribution on the x-axis. If the quantiles line up then we can say that our data is fairly normal. What exactly is a quantile? This is a division of the data distribution into roughly equal portions.

Here is an example of a QQ plot for the normally distributed data that we just created using the stat_qq() function of the ggplot2 package:

Here we can see that the quantiles are fairly similar between the observed and theoretical data. We see that the points mostly fall on the line, however there are some points that are a bit further from the line as we get to the extreme quantiles. Notice that the sample quantiles (which will be fairly similar to our real BMI data quantiles) on the y-axis has the same range as the values that we created. So values that are bellow 22 for example are represented as the points bellow 22 on the y-axis. As expected we see that about half the points are bellow our mean of 24.

If we were to use different data that had a range of different values our y-axis would shift according to the range of values. For example the Orange data within the installation of R includes data about the circumference of orange trees in millimeters. Here we can see that the quantiles are quite different but reflect the range of orange tree circumferences.

[1]  30 214

Let’s take a look at our BMI data:

For the sake of simplicity, we are going to focus on the data from the women. This is because women were identified in the paper to have larger increases in BMI. If we want to perform tests on these groups specifically, then we need to know how this data looks.

What about by region and year? If we compare these data then we need to look at the distribution of each of these subsets.

We can see that at the extremes of our quantiles, for most of our data, our tails are not very similar to the theoretical distribution. The Rural data looks more normal than the urban data, but if we were to use statistical tests that rely on normality, this would require that both groups are normally distributed.

Finally, some statisticians also use the Shapiro-Wilk test for normality when the QQ plot is a bit unclear. Many statisticians however would conclude from the QQ plots that normality has been violated.

Shapiro-Wilk test

For illustrative purposes we will show how we can use the dplyr summarize() and group_by() functions to perform the Shapiro-Wilk test for all the subsets we are interested in.


    Shapiro-Wilk normality test

data:  .
W = 0.9887, p-value = 0.1146
# A tibble: 6 x 3
# Groups:   Year [2]
  Year  Region   shapiro_test
  <chr> <chr>           <dbl>
1 1985  National  0.0000478  
2 1985  Rural     0.000679   
3 1985  Urban     0.000000332
4 2017  National  0.00363    
5 2017  Rural     0.0108     
6 2017  Urban     0.0000130  

We see that all the data does not appear to be normally distributed.

Data Analysis

We are interested in comparing the means of female rural and urban BMI measurements for both years. There are two possible classes of statistical tests that we could run to compare the means of these two groups:

  1. Parametric
  2. nonparametric

Parametric two sample mean tests

Often when comparing two groups we might perform a two sample t test to determine if the means of each group is different. The two sample t test however, relies on several assumptions:

  1. The data for both groups is normally distributed
  2. The variance of both groups is similar

If these assumptions are violated, this doesn’t necessarily mean we can’t perform a t test. It just means we may have to transform the data to make it normally distributed and we may need to perform the t test in a special way to account for the difference in the variance in the two groups. Alternatively, we can use a nonparametric test like the Wilcoxon–Mann–Whitney (WMW) test. We will explore both of these options.

The t test is also fairly robust to non-normality if the data is relatively large, and we have an n of 200, which should be sufficient but let’s investigate the nonparametric tests further.

Often we would check if the variance of the rural and urban data is equal using the var.test() function. However this is an F test and assumes that the data is normally distributed. Instead we will use the mood.test() function which performs the Mood’s two-sample test for a difference in scale parameters and does not assume that the data is normally distributed.


    Mood two-sample test of scale

data:  pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Urban"), BMI)
Z = 2.9189, p-value = 0.003513
alternative hypothesis: two.sided

    Mood two-sample test of scale

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==     "Rural"), BMI) and     "Urban"), BMI)
Z = 3.1305, p-value = 0.001745
alternative hypothesis: two.sided

    Mood two-sample test of scale

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Rural"), BMI)
Z = -0.24228, p-value = 0.8086
alternative hypothesis: two.sided

    Mood two-sample test of scale

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Urban"), BMI) and     "Urban"), BMI)
Z = 1.5317, p-value = 0.1256
alternative hypothesis: two.sided

Our p value is less than .05 for both tests, thus we reject our null hypothesis that there is no difference in the variance. Therefore, we conclude that the variance is not equal and that our data also violates this assumption.

We will perform a special t.test where we account for the fact that our variance is not equal.

Another important consideration is that the data is what we call paired. Meaning the measurements from the rural and urban areas are not independent. That is because we have a rural and urban measurement mean for nearly every country. Thus these values may be more similar to one another if they come from the same country.


    Paired t-test

data:  pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Urban"), BMI)
t = -10.356, df = 194, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.0573625 -0.7190478
sample estimates:
mean of the differences 
             -0.8882051 

    Paired t-test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==     "Rural"), BMI) and     "Urban"), BMI)
t = -14.095, df = 195, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -1.1870263 -0.8956268
sample estimates:
mean of the differences 
              -1.041327 

    Paired t-test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Rural"), BMI)
t = -22.119, df = 195, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -2.591762 -2.167422
sample estimates:
mean of the differences 
              -2.379592 

    Paired t-test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Urban"), BMI) and     "Urban"), BMI)
t = -24.378, df = 198, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -2.383938 -2.027118
sample estimates:
mean of the differences 
              -2.205528 

Now we will try transform our data to make it more normally distributed. One way to do this is to take the logarithm of the data values. Then we will see how this influences the results.

# A tibble: 6 x 3
# Groups:   Year [2]
  Year  Region   shapiro_test
  <chr> <chr>           <dbl>
1 1985  National     0.00315 
2 1985  Rural        0.0105  
3 1985  Urban        0.000334
4 2017  National     0.293   
5 2017  Rural        0.0784  
6 2017  Urban        0.00416 
# A tibble: 6 x 3
# Groups:   Year [2]
  Year  Region   shapiro_test
  <chr> <chr>           <dbl>
1 1985  National  0.0000478  
2 1985  Rural     0.000679   
3 1985  Urban     0.000000332
4 2017  National  0.00363    
5 2017  Rural     0.0108     
6 2017  Urban     0.0000130  

Let’s see the results of the t test with the transformed data:


    Paired t-test

data:  pull(filter(BMI_long_log, Sex == "Women", Year == "2017", Region ==  and pull(filter(BMI_long_log, Sex == "Women", Year == "2017", Region ==     "Rural"), log_BMI) and     "Urban"), log_BMI)
t = -10.058, df = 194, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.04242774 -0.02851589
sample estimates:
mean of the differences 
            -0.03547182 

    Paired t-test

data:  pull(filter(BMI_long_log, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long_log, Sex == "Women", Year == "1985", Region ==     "Rural"), log_BMI) and     "Urban"), log_BMI)
t = -13.962, df = 195, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.05214677 -0.03923811
sample estimates:
mean of the differences 
            -0.04569244 

    Paired t-test

data:  pull(filter(BMI_long_log, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long_log, Sex == "Women", Year == "2017", Region ==     "Rural"), log_BMI) and     "Rural"), log_BMI)
t = -22.369, df = 195, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.10617051 -0.08896626
sample estimates:
mean of the differences 
            -0.09756839 

    Paired t-test

data:  pull(filter(BMI_long_log, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long_log, Sex == "Women", Year == "2017", Region ==     "Urban"), log_BMI) and     "Urban"), log_BMI)
t = -23.977, df = 198, p-value < 2.2e-16
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
 -0.09377834 -0.07952498
sample estimates:
mean of the differences 
            -0.08665166 

The data appears to be more similar to the normal distribution, but most subsets still fail the Shapiro-Wilk normality test. Again, our sample size of 200 is quite large and the t test is generally quite robust to violations of normality with large n, thus the modified t test to account for unequal variance might be a good option using the log normalized data, as it is at least more normally distributed. However, let’s take a look at non parametric tests, which are also a great option when the assumptions of the t test are violated.

Nonparametric two sample mean tests

There are two options to consider when the assumptions of the t test are violated. The Wilcoxon signed rank test and the Two-sample Kolmogorov-Smirnov test both do not assume normality. Thus these tests should be considered when the data of either groups does not appear to be normally distributed and particularly when the number of samples is low.

Importantly the Kolmogorov-Smirnov test does not assume normality or equal variance, while the Wilcoxon signed rank test does assume equal variance. Here is how you would perform these tests. However in our case, because the variance is not equal between our groups of interest, the Kolmogorov-Smirnov test would be more appropriate.


    Two-sample Kolmogorov-Smirnov test

data:  pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Urban"), BMI)
D = 0.20006, p-value = 0.0007385
alternative hypothesis: two-sided

    Two-sample Kolmogorov-Smirnov test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==     "Rural"), BMI) and     "Urban"), BMI)
D = 0.19914, p-value = 0.0007779
alternative hypothesis: two-sided

##What about the difference in female BMI from 1985 to 2017 for both regions?


    Two-sample Kolmogorov-Smirnov test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Rural"), BMI) and     "Rural"), BMI)
D = 0.38359, p-value = 5.553e-13
alternative hypothesis: two-sided

    Two-sample Kolmogorov-Smirnov test

data:  pull(filter(BMI_long, Sex == "Women", Year == "1985", Region ==  and pull(filter(BMI_long, Sex == "Women", Year == "2017", Region ==     "Urban"), BMI) and     "Urban"), BMI)
D = 0.43216, p-value < 2.2e-16
alternative hypothesis: two-sided

Data Visualization

Again we will utilize ggplot2 to create plots.If you need additional information please see here. The top two lines of the code for the following plots, filter the data to only specific values of interest. Then we layer what is called a jitter on top of a box plot. A jitter is essentially a dot plot but with some variation on the location of the points so that they do not line up vertically which can make the individual points difficult to see.

Let’s look at the national mean BMI estimates for each of the years:

Now Let’s look at the change in rural and urban mean BMI estimates:

How do the different countries compare? Or in other words what do the individual dots represent in our box plots? We will take a look using geom_label():

If we include all country names this is a bit too much… so perhaps we should focus on just the extreme BMI values using filter() function of thedplyr package. We will also use the ggrepel package to have our labels not overlap each other.

And let’s fill the box plots with color and outline in black:

Overall differences

Let’s take a look at all the data together:

That’s useful, but let’s look at the individual points and include our country labels, to do so lets change our United States of America label to USA:

BMI_long$Country <-BMI_long$Country %>%str_replace( pattern = "United States of America", replacement = "USA")


ggplot(BMI_long, aes(x = Year, y = BMI, col = Year)) + 
  geom_boxplot(outlier.shape = NA, color = "black" , aes(fill = Year)) + 
  facet_grid(~Sex + Region) + 
  geom_hline(yintercept=30, linetype="dashed", color = "red", size =1)  + 
  # This will add a horizontal dashed line to indicate BMI values considered to be in the range of obesity
  geom_jitter(data=subset(BMI_long), aes(x =Year, y =BMI), width = .2, size =2, shape =21, color = "black", fill = "gray")  + 
  # This will add the individual country data points
  # The shape 21 allows for a different fill and outline color ( the outline is the "color")
  # The width determines how wide the jitter points are plotted
  geom_jitter(data=subset(BMI_long, Country == "USA"), aes(x =Year, y =BMI), width = .02, size =12, shape =21, color = "black", fill = "gray") + 
  # This will add points that are larger for the USA data
  geom_text(data=subset(BMI_long,  Country == "USA"), aes(x =Year, y =BMI,label=Country), color = "black") + 
  # This will add USA labels to the USA points
  theme(legend.position = "none", 
  # This is useful for removing the legend
        axis.text.x = element_text(size = 15,angle = 30), 
        # this changes the size and angle of the x axis point labels 
        axis.text.y = element_text(size = 20), 
        axis.title.y = element_text(size =15), 
        axis.title.x = element_text(size =15), 
        strip.text.x = element_text(size = 15)) +
  # This changes the size of x axis labels for the facet 
        ggtitle( "Differences in BMI Over Time and Across Region Type and Gender") # Add a  plot title

Here we can see that overall BMI appears to be increasing globally over time. Additionally we can see that this is occurring not just in urban areas, but also in rural areas. The US is consistently above the median in all strata of the data. In general, the female data shows higher BMI values than the male data. The rural USA BMI appears to be higher than the urban BMI for both men and women. Many countries have average BMI estimates above the obesity threshold of 30. Thus it appears that education and outreach programs for weight management should focus on both rural and urban areas and both genders. Education and assistance for women may be especially helpful.

Differences in rate of increase

How does the rate of increase in BMI differ between groups? Which group might especially need attention?

First let’s calculate the differences in BMI from 2017 and 1985 and add this to our BMI_long data object:

# A tibble: 6 x 4
  Country     Sex   Type             Difference
  <fct>       <chr> <chr>                 <dbl>
1 Afghanistan Men   Rural_difference     2.8   
2 Afghanistan Women Rural_difference     3.5   
3 Albania     Men   Rural_difference     1.90  
4 Albania     Women Rural_difference     0.1000
5 Algeria     Men   Rural_difference     3     
6 Algeria     Women Rural_difference     3.70  

Let’s replace “United states of America” with “USA” and make a plot with this data to compare the change in BMI:

We can now see that the rate of change appears to be larger in the women compared to the men. The group with the largest increase in the USA is the women living in rural areas. Thus this group should be especially focused on to improve this public health issue.

Now let’s make a plot that summarizes the last two plots. To do this we will simplify the other two plots and then combine them together.

# simplified national means plot
Means_plot<-BMI_long %>% 
  filter(Sex %in% c("Men", "Women"), Year %in% c("1985", "2017"), Region == "National") %>%
ggplot(aes(x = Sex, y = BMI)) + 
  geom_boxplot(outlier.shape = NA, color = "black" , aes(fill = Sex)) + 
 scale_fill_manual(values=c("dodgerblue", "orchid2"))+
  facet_grid(~Year) + 
  geom_hline(yintercept=30, linetype="dashed", color = "red", size =1)  + 
  geom_jitter(data=BMI_long 
                          %>%filter(Sex %in% c("Men", "Women"), Year %in% c("1985", "2017"), Region == "National"),
                          aes(x =Sex, y =BMI), width = .2, size =2, shape =21, color = "black", fill = "gray") +
  geom_jitter(data=subset(BMI_long 
                          %>%filter(Sex %in% c("Men", "Women"), Year %in% c("1985", "2017"), Region == "National"), 
                          Country == "USA"), aes(x =Sex, y =BMI), width = .02, size =12, shape =21, color = "black", fill = "gray") + 
  # This will add points that are larger for the USA data
  geom_text(data=subset(BMI_long
                        %>%filter(Sex %in% c("Men", "Women"), Year %in% c("1985", "2017"), Region == "National"),
                        Country == "USA"), aes(x =Sex, y =BMI,label=Country), color = "black") + 
  # This will add USA labels to the USA points
  theme(legend.position = "none", 
  # This is useful for removing the legend
        axis.text.x = element_text(size = 15,angle = 30), 
        # this changes the size and angle of the x axis point labels 
        axis.text.y = element_text(size = 20), 
        axis.title.y = element_text(size =15), 
        axis.title.x = element_text(size =15), 
        strip.text.x = element_text(size = 15))
   
#Simplified difference plot 
BMI_diff_long$Type <-BMI_diff_long$Type %>%str_replace( pattern = "_difference", replacement = "")

Diff_plot<-BMI_diff_long %>% 
  filter(Sex %in% c("Men", "Women"), Type != "National") %>%
ggplot( aes(x = Type, y = Difference, col = Type)) + 
  geom_boxplot(outlier.shape = NA, color = "black" , aes(fill = Sex)) + 
  scale_fill_manual(values=c("dodgerblue", "orchid2"))+
  facet_grid(~Sex) +
  geom_jitter(data=BMI_diff_long %>% 
    filter(Sex %in% c("Men", "Women"), Type != "National") , 
    aes(x =Type, y =Difference), width = .2, size =2, shape =21, color = "black", fill = "gray")  + 
  geom_jitter(data=subset(BMI_diff_long %>% 
    filter(Sex %in% c("Men", "Women"), Type != "National") , Country == "USA"), 
    aes(x =Type, y =Difference), width = .02, size =12, shape =21, color = "black", fill = "gray") + 
  # This will add points that are larger for the USA data
  geom_text(data=subset(BMI_diff_long %>% 
    filter(Sex %in% c("Men", "Women"), Type != "National") , Country == "USA"),
    aes(x =Type, y =Difference,label=Country), color = "black") + 
  # This will add USA labels to the USA points
  theme(legend.position = "none", 
  # This is useful for removing the legend
        axis.text.x = element_text(size = 15,angle = 30), 
        # this changes the size and angle of the x axis point labels 
        axis.text.y = element_text(size = 20), 
        axis.title.y = element_text(size =15), 
        axis.title.x = element_text(size =15), 
        strip.text.x = element_text(size = 15)) # this changes the size of x axis labels for the facet

Diff_plot<-Diff_plot + labs(title = "Change in BMI by region", x = "", y = "Increase in BMI \n (1985 to 2017)")+
    theme(title = element_text (size = 12, face = "bold"))
Means_plot <-Means_plot + labs(title = "Mean BMI over time", x = "", y = "Mean BMI")+
    theme(title = element_text (size = 12, face = "bold"))

cowplot::plot_grid(Means_plot, Diff_plot, labels = c("A", "B"))

Great, now we have put two plots together using the plot_grid() function of the cowplot package. This way we can clearly communicate two messages. The first being that BMI has increased over time globally and that many countries including the United States of America are approaching a mean BMI that is above the obesity threshold of 30. We can also see that Women have larger BMI values, but that both genders show increased levels over time. In the second plot we can see that the increase in BMI is not just happening in urban communities, but in both rural and urban communities. In fact, Women in rural areas of the United States of America appear to have the largest increase in BMI.

Summary

We have evaluated BMI average estimates from 200 different countries around the world. To do so we imported data from a pdf using the pdftools package. We used tidyverse packages such as dplyr, stringr, and tidy to clean the data and get it in a workable format. Our statistical analysis focused on evaluating differences in BMI in females around the world across time and between rural and urban areas. We found a significant difference both between years and between the type of community using t tests and nonparametric tests. Thus BMI has increased in women since 1985. Although BMI estimates are significantly higher in Urban areas compared to rural areas, BMI estimates have increased in both regions. Using the ggplot2 package we were able to visualize trends in the data. Importantly, the largest increase appears to be in the rural areas particularly for women. Analyses like this are important for defining which groups could benefit the most from interventions, education, and policy changes when attempting to mitigate public health challenges.

Suggested Homework

Students can evaluate the change in BMI over time using the global data available for each year between 2015 and 2017. This data can be found here.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgLSBSdXJhbCBhbmQgVXJiYW4gT2Jlc2l0eSIKY3NzOiBzdHlsZS5jc3MKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgIGhpZ2hsaWdodDogdGFuZ28KICAgIG51bWJlcl9zZWN0aW9uczogbm8KICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDogeWVzCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKICB3b3JkX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgoKCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoaW5jbHVkZSA9IFRSVUUsIGNvbW1lbnQgPSBOQSwgZWNobyA9IFRSVUUsCiAgICAgICAgICAgICAgICAgICAgICBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmcgPSBGQUxTRSkKYGBgCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJtYWlucGxvdDIucG5nIikpCmBgYAoKIyMgTW90aXZhdGlvbgpCTUkgaXMgbWVhc3VyZWQgYXMgYW4gaW5kaXZpZHVhbCdzIHdlaWdodCBpbiBraWxvZ3JhbXMgZGl2aWRlZCBieSB0aGUgaW5kaXZpZHVhbCdzIGhlaWdodCBpbiBtZXRlcnMgc3F1YXJlZC4gRGlmZmVyZW50IGNhdGVnb3JpZXMgb2Ygd2VpZ2h0IGFyZSBkZWZpbmVkIHdpdGggdGhlIGZvbGxvd2luZyBjdXRvZmZzOgoKIVtdKGh0dHBzOi8vY2RuLnZlcnRleDQyLmNvbS9FeGNlbFRlbXBsYXRlcy9JbWFnZXMvYm1pLWNoYXJ0LmdpZikKCkFuIFthcnRpY2xlXShodHRwczovL3d3dy5uYXR1cmUuY29tL2FydGljbGVzL3M0MTU4Ni0wMTktMTE3MS14LnBkZikgcHVibGlzaGVkIGluIE5hdHVyZSBldmFsdWF0ZWQgYW5kIGNvbXBhcmVkIHRoZSBCb2R5LU1hc3MgSW5kZXggKEJNSSkgb2YgcG9wdWxhdGlvbnMgaW4gcnVyYWwgYW5kIHVyYmFuIGNvbW11bml0aWVzIGFyb3VuZCB0aGUgd29ybGQ6IAoKYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSIxMDAlIiwgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShoZXJlKQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJwYXBlci5wbmciKSkKCmBgYAoKIyMjIyB7LnBhcnRpY3VsYXJfdG9waWNfYmxvY2t9Ck5DRCBSaXNrIEZhY3RvciBDb2xsYWJvcmF0aW9uwqAoTkNELVJpc0MpLiBSaXNpbmcgcnVyYWwgYm9keS1tYXNzIGluZGV4IGlzIHRoZSBtYWluIGRyaXZlciBvZiB0aGUgZ2xvYmFsIG9iZXNpdHkgZXBpZGVtaWMgaW4gYWR1bHRzLiAqTmF0dXJlKiA1NjksIDI2MOKAkzI2NCAoMjAxOSkuIAoKIyMjIwpUaGlzIGFydGljbGUgY2hhbGxlbmdlZCB0aGUgd2lkZWx5LWhlbGQgdmlldyB0aGF0IGluY3JlYXNlZCB1cmJhbml6YXRpb24gd2FzIG9uZSBvZiB0aGUgbWFqb3IgcmVhc29ucyBmb3IgaW5jcmVhc2VkIGdsb2JhbCBvYmVzaXR5IHJhdGVzLiBUaGlzIHZpZXcgY2FtZSBhYm91dCBiZWNhdXNlIG1hbnkgY291bnRyaWVzIGFyb3VuZCB0aGUgd29ybGQgaGF2ZSBzaG93biBpbmNyZWFzZWQgdXJiYW5pemF0aW9uIGxldmVscyBpbiBwYXJhbGxlbCB3aXRoIGluY3JlYXNlZCBvYmVzaXR5IHJhdGVzLiBIb3dldmVyIHRoaXMgc3R1ZHkgZGVtb25zdHJhdGVkIHRoYXQgdGhpcyBtaWdodCBub3QgYmUgdGhlIGNhc2UuIFRoaXMgY2FzZSBzdHVkeSB3aWxsIGV2YWx1YXRlIHRoZSBkYXRhIHJlcG9ydGVkIGluIHRoaXMgYXJ0aWNsZSB0byBleHBsb3JlIHJlZ2lvbmFsIGFuZCBnZW5kZXIgc3BlY2lmaWMgZGlmZmVyZW5jZXMgaW4gdGhlIG9iZXNpdHkgcmF0ZXMgYXJvdW5kIHRoZSB3b3JsZCBpbiAxOTg1IGFuZCAyMDE3LiBNb3N0IGltcG9ydGFudGx5IHdlIHdpbGwgdGVzdCBpZiB0aGVyZSBpcyBhIGRpZmZlcmVuY2UgaW4gb2Jlc2l0eSByYXRlcyBiZXR3ZWVuIHJ1cmFsIGFuZCB1cmJhbiBjb21tdW5pdGllcy4gCgo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zIGFyZTogPC91PjwvYj4KCjEpIElzIHRoZXJlIGEgZGlmZmVyZW5jZSBiZXR3ZWVuIHJ1cmFsIGFuZCB1cmJhbiBCTUkgZXN0aW1hdGVzIGFyb3VuZCB0aGUgd29ybGQ/CjIpIEhvdyBoYXZlIEJNSSBlc3RpbWF0ZXMgY2hhbmdlZCBmcm9tIDE5ODUgdG8gMjAxNz8KMykgSG93IGRvIGRpZmZlcmVudCBjb3VudHJpZXMgY29tcGFyZSBmb3IgQk1JIGVzdGltYXRlcy0gaW4gcGFydGljdWxhciwgaG93IGRvZXMgdGhlIFVuaXRlZCBTdGF0ZXMgY29tcGFyZSB0byB0aGUgcmVzdCBvZiB0aGUgd29ybGQ/CgpJbiB0aGlzIGNhc2Ugc3R1ZHksIHdl4oCZbGwgd2FsayB5b3UgdGhyb3VnaCBpbXBvcnRpbmcgZGF0YSBmcm9tIGEgcGRmLCBjbGVhbmluZyBkYXRhLCB3cmFuZ2xpbmcgZGF0YSwgdmlzdWFsaXppbmcgdGhlIGRhdGEsIGFuZCBjb21wYXJpbmcgdGhlIG1lYW5zIG9mIHR3byBncm91cHMgdXNpbmcgd2VsbC1lc3RhYmxpc2hlZCBhbmQgY29tbW9ubHkgdXNlZCBwYWNrYWdlcywgaW5jbHVkaW5nIGBzdHJpbmdyYCwgYHRpZHlyYCwgYGRwbHlyYCwgYHB1cnJyYCwgYW5kIGBnZ3Bsb3QyYC4gV2Ugd2lsbCBlc3BlY2lhbGx5IGZvY3VzIG9uIHVzaW5nIHBhY2thZ2VzIGFuZCBmdW5jdGlvbnMgZnJvbSB0aGUgW1RpZHl2ZXJzZV0oaHR0cHM6Ly93d3cudGlkeXZlcnNlLm9yZy8pLiBUaGUgVGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IHRoZSBjaGllZiBzY2llbnRpc3QgYXQgUlN0dWRpbywgSGFkbGV5IFdpY2toYW0uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KCmBgYHtyLCBvdXQud2lkdGggPSAiMjAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQpsaWJyYXJ5KGtuaXRyKQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3RpZHl2ZXJzZS50aWR5dmVyc2Uub3JnL2xvZ28ucG5nIikKYGBgCgoKCldlIHdpbGwgYmVnaW4gYnkgbG9hZGluZyB0aGUgcGFja2FnZXMgdGhhdCB3ZSB3aWxsIG5lZWQ6CmBgYHtyfQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkocGRmdG9vbHMpCmxpYnJhcnkoc3RyaW5ncikKbGlicmFyeShyZWFkcikKbGlicmFyeShkcGx5cikKbGlicmFyeSh0aWJibGUpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KGdncmVwZWwpCmxpYnJhcnkoY293cGxvdCkKCmBgYAoKCiBQYWNrYWdlICAgfCBVc2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLS0tLS0tLS0gfC0tLS0tLS0tLS0tLS0KW2hlcmVdKGh0dHBzOi8vZ2l0aHViLmNvbS9qZW5ueWJjL2hlcmVfaGVyZSkgICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhCltwZGZ0b29sc10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3BkZnRvb2xzL3BkZnRvb2xzLnBkZikgICB8IHRvIHJlYWQgYSBwZGYgaW50byBSICAgCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy9hcnRpY2xlcy9zdHJpbmdyLmh0bWwpICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB3aXRoaW4gdGhlIHBkZiBvZiB0aGUgZGF0YSAKW3JlYWRyXShodHRwczovL3JlYWRyLnRpZHl2ZXJzZS5vcmcvKSAgICAgIHwgdG8gbWFuaXB1bGF0ZSB0aGUgdGV4dCB3aXRoaW4gdGhlIHBkZiBvZiB0aGUgZGF0YSBpbnRvIGluZGl2aWR1YWwgbGluZXMgIApbZHBseXJdKGh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy8pICAgICAgfCB0byBhcnJhbmdlL2ZpbHRlci9zZWxlY3Qgc3Vic2V0cyBvZiB0aGUgZGF0YSAKW3RpYmJsZV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8pICAgICB8IHRvIGNyZWF0ZSBkYXRhIG9iamVjdHMgdGhhdCB3ZSBjYW4gbWFuaXB1bGF0ZSB3aXRoIGRwbHlyL3N0cmluZ3IvdGlkeXIvcHVycnIKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvbWFncml0dHIuaHRtbCkgICB8IHRvIHVzZSB0aGUgYCU8PiVgIHBpcHBpbmcgb3BlcmF0b3IKW3B1cnJyXShodHRwczovL3B1cnJyLnRpZHl2ZXJzZS5vcmcvKSAgICAgIHwgdG8gcGVyZm9ybSBmdW5jdGlvbnMgb24gYWxsIGNvbHVtbnMgb2YgYSB0aWJibGUKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKSAgICAgIHwgdG8gY29udmVydCBkYXRhIGZyb20gd2lkZSB0byBsb25nIGZvcm1hdApbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKSAgICB8IHRvIG1ha2UgdmlzdWFsaXphdGlvbnMgd2l0aCBtdWx0aXBsZSBsYXllcnMKW2RhdGEudGFibGVdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9kYXRhLnRhYmxlL3ZpZ25ldHRlcy9kYXRhdGFibGUtaW50cm8uaHRtbCkgfCB0byBjcmVhdGUgZGF0YSBvYmplY3RzIHRoYXQgYXJlIHNpbWlsYXIgdG8gdGliYmxlcyBidXQgZGlmZmVyZW50CltnZ3JlcGVsXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvZ2dyZXBlbC92aWduZXR0ZXMvZ2dyZXBlbC5odG1sKSAgICB8IHRvIGFsbG93IGxhYmVscyBpbiBmaWd1cmVzIG5vdCB0byBvdmVybGFwCltjb3dwbG90XShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvY293cGxvdC92aWduZXR0ZXMvaW50cm9kdWN0aW9uLmh0bWwpIHwgdG8gYWxsb3cgcGxvdHMgdG8gYmUgY29tYmluZWQKX19fCgoKVGhlIGZpcnN0IHRpbWUgd2UgdXNlIGEgZnVuY3Rpb24sIHdlIHdpbGwgdXNlIHRoZSBgOjpgIHRvIGluZGljYXRlIHdoYXQgcGFja2FnZSB3ZSBhcmUgdXNpbmcuIFVubGVzcyB3ZSBoYXZlIG92ZXJsYXBwaW5nIGZ1bmN0aW9uIG5hbWVzLCB0aGlzIGlzIG5vdCBuZWNlc3NhcnksIGJ1dCB3ZSB3aWxsIGluY2x1ZGUgaXQgaGVyZSB0byBpbGx1c3RyYXRlIHdoYXQgcGFja2FnZSB3ZSBhcmUgdXNpbmcuCgoKIyMjIENvbnRleHQKClRoZSBtZWFzdXJlbWVudCBvZiBCTUkgaGFzIHNvbWUgW2xpbWl0YXRpb25zXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUM0ODkwODQxL3BkZi9udC01MC0xMTcucGRmKSB0aGF0IGFyZSB3ZWxsIHJlY29nbml6ZWQsIGFzIGl0IGRvZXMgbm90IGFjY291bnQgZm9yIHRoZSBjb21wb3NpdGlvbiBvZiBib2R5IG1hc3MsIHRoZSBsb2NhdGlvbiBvZiBib2R5IGZhdCwgb3IgdGhlIGNvbnRyaWJ1dGlvbiBvZiBib2R5IGZyYW1lIHNpemUuIEhvd2V2ZXIsIFtCTUkgaGFzIGJlZW4gYSB1c2VmdWwgaGVhbHRoIGluZGljYXRvcl0oaHR0cHM6Ly9qb3VybmFscy5sd3cuY29tL2Fjc20taGVhbHRoZml0bmVzcy9GdWxsdGV4dC8yMDE2LzA3MDAwL1RIRV9CRU5FRklUU19PRl9CT0RZX01BU1NfSU5ERVhfQU5EX1dBSVNULjguYXNweCNwZGYtbGluaykgZm9yIHJpc2sgZm9yIG1hbnkgZGlzZWFzZXMgcGFydGljdWxhcmx5IHdoZW4gY29tYmluZWQgd2l0aCBvdGhlciByaXNrIGZhY3RvciBpbmZvcm1hdGlvbi4KCiMjIFdoYXQgYXJlIHRoZSBkYXRhPwoKV2Ugd2lsbCBiZSB1c2luZyBkYXRhIGxvY2F0ZWQgd2l0aGluIGEgdGFibGUgb2YgdGhlIFtzdXBwbGVtZW50YXJ5IG1hdGVyaWFsXShodHRwczovL3N0YXRpYy1jb250ZW50LnNwcmluZ2VyLmNvbS9lc20vYXJ0JTNBMTAuMTAzOCUyRnM0MTU4Ni0wMTktMTE3MS14L01lZGlhT2JqZWN0cy80MTU4Nl8yMDE5XzExNzFfTU9FU00xX0VTTS5wZGYpIGZvciB0aGUgTkNELVJpc0MgcGFwZXIgcmVmZXJlbmNlZCBhYm92ZS4gVGhpcyBpcyBhIHBkZiB0aGF0IGNhbiBiZSBmb3VuZCBmcmVlbHkgYXZhaWxhYmxlIG9ubGluZS4KCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJmaXJzdF9wYWdlLnBuZyIpKQpgYGAKCkhlcmUgeW91IGNhbiBzZWUgdGhhdCB0aGUgZGF0YSBjb250YWlucyBtZWFuIEJNSSB2YWx1ZXMgZm9yIGJvdGggTWVuIGFuZCBXb21lbiBpbiB2YXJpb3VzIGNvdW50cmllcyBhdCB0aGUgbmF0aW9uYWwgbGV2ZWwsIGFzIHdlbGwgYXMgdGhlIG1lYW4gQk1JIHZhbHVlcyBmb3IgdGhlIHJ1cmFsIGFuZCB1cmJhbiBhcmVhcyBvZiB0aGVzZSBjb3VudHJpZXMgZm9yIGJvdGggMTk4NSBhbmQgMjAxNy4KClRoZSBkYXRhIHdpdGhpbiB0aGUgcGFyZW50aGVzZXMgYXJlIHRoZSA5NSAlIDxiPmNyZWRpYmxlIGludGVydmFsPC9iPiAoQ0lzKSByYW5nZXMgZm9yIHRoZSBtZWFuIEJNSSBlc3RpbWF0ZXMuIFRoZSBhdXRob3JzIHByb3ZpZGUgdGhlc2UgQ0lzIGFzIGEgZ3VpZGUgdG8gdW5kZXJzdGFuZCBob3cgbGlrZWx5IHRoZSBlc3RpbWF0ZSBpcyBmb3IgdGhlIHRydWUgcG9wdWxhdGlvbiBtZWFuIEJNSS4gQSB3aWRlciByYW5nZSBzdWdnZXN0cyB0aGF0IHRoZSBlc3RpbWF0ZSBpcyBsZXNzIGFjY3VyYXRlLCBhcyB0aGVyZSBhcmUgbW9yZSBwb3NzaWJsZSB2YWx1ZXMgZm9yIHRoZSB0cnVlIG1lYW4gd2l0aCBjcmVkaWJsZSBldmlkZW5jZS4KCjx1Pk5vdGU6PC91PiBXaGlsZSBbZ2VuZGVyXShodHRwczovL3d3dy5nZW5kZXJzcGVjdHJ1bS5vcmcvcXVpY2stbGlua3MvdW5kZXJzdGFuZGluZy1nZW5kZXIvKSBhbmQgW3NleF0oaHR0cHM6Ly93d3cud2hvLmludC9nZW5vbWljcy9nZW5kZXIvZW4vaW5kZXgxLmh0bWwpIGFyZSBub3QgYWN0dWFsbHkgYmluYXJ5LCB0aGUgZGF0YSBwcmVzZW50ZWQgdGhhdCBpcyB1c2VkIGluIHRoaXMgYW5hbHlzaXMgb25seSBjb250YWlucyBkYXRhIGZvciBncm91cHMgb2YgaW5kaXZpZHVhbHMgZGVzY3JpYmVkIGFzIG1lbiBvciB3b21lbi4gCgojIyBEYXRhIEltcG9ydAoKRmlyc3QgbGV0J3MgZG93bmxvYWQgdGhlIGRhdGE6CmBgYHtyfQoKdXJsIDwtICJodHRwczovL3N0YXRpYy1jb250ZW50LnNwcmluZ2VyLmNvbS9lc20vYXJ0JTNBMTAuMTAzOCUyRnM0MTU4Ni0wMTktMTE3MS14L01lZGlhT2JqZWN0cy80MTU4Nl8yMDE5XzExNzFfTU9FU00xX0VTTS5wZGYiCnV0aWxzOjpkb3dubG9hZC5maWxlKHVybCwgInBhcGVyX3N1cHBsZW1lbnQucGRmIikKYGBgCgpOb3cgdGhhdCB3ZSBoYXZlIHRoZSBvYmVzaXR5IHBkZiwgd2Ugd2lsbCByZWFkIGl0IGluIHRvIFIgdXNpbmcgdGhlIGBwZGZ0b29sc2AgcGFja2FnZToKCmBgYHtyfQpwZGZfb2Jlc2l0eTwtcGRmdG9vbHM6OnBkZl90ZXh0KGhlcmUoInBhcGVyX3N1cHBsZW1lbnQucGRmIikpCiMgUERGIGVycm9yOiBFeHBlY3RlZCB0aGUgb3B0aW9uYWwgY29udGVudCBncm91cCBsaXN0LCBidXQgd2Fzbid0IGFibGUgdG8gZmluZCBpdCwgb3IgaXQgaXNuJ3QgYW4gQXJyYXkKIyBlcnJvcnMgbGlrZSB0aGlzIGNhbiBiZSBjb21tb24gd2l0aCBQREZzLi4uIHdlIGNhbiB0YWtlIGEgbG9vayBhdCB0aGUgZGF0YSB0byBzZWUgaWYgaXQgc3RpbGwgbG9va3MgYXMgZXhwZWN0ZWQKYGBgCgpMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgZGF0YS0gdGhlIGBzdW1tYXJ5KClgIGZ1bmN0aW9uIGhlbHBzIHVzIHRvIGxvb2sgYXQgdGhlIHN0cnVjdHVyZSBvZiBSIG9iamVjdHMuCgpgYGB7cn0Kc3VtbWFyeShwZGZfb2Jlc2l0eSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgd2UgaGF2ZSA2MyBlbGVtZW50cyB0aGF0IGFyZSBjaGFyYWN0ZXIgc3RyaW5ncy4gWW91IG1heSBhbHNvIG5vdGljZSB0aGF0IHRoZSBvcmlnaW5hbCBQREYgaGFzIDYzIHBhZ2VzLiBMZXQncyB0YWtlIGEgbG9vayBhdCBzb21lIG9mIHRoZXNlIGVsZW1lbnRzLgoKYGBge3J9CnBkZl9vYmVzaXR5WzFdICMgdGhpcyBsb29rcyBsaWtlIHRoZSBmaXJzdCBwYWdlCnBkZl9vYmVzaXR5WzJdICMgdGhpcyBsb29rcyBsaWtlIHRoZSBzZWNvbmQgcGFnZQpgYGAKCmBgYHtyLCBldmFsID0gRkFMU0V9CnBkZl9vYmVzaXR5WzU1XSAKIyB0aGlzIGxvb2tzIGxpa2UgZGF0YSBpbiBhIHRoZSB0YWJsZSB3ZSBhcmUgaW50ZXJlc3RlZCBpbgpgYGAKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iMTAwJSIsIG1lc3NhZ2U9RkFMU0V9CmxpYnJhcnkoaGVyZSkKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgicGFnZTU1LnBuZyIpKQoKYGBgCgoKV2UgY2FuIHNlZSB0aGF0IHRoZSBvdXRwdXQgbG9va3MgcHJldHR5IHNpbWlsYXIgdG8gdGhlIHBhZ2VzIG9mIHRoZSBwZGYsIGJ1dCB0aGUgc3BhY2luZyBpcyBxdWl0ZSBhd2t3YXJkLiBUaGUgd2F5IHRoZSBkYXRhIGlzIGRpc3BsYXllZCBpcyBwYXJ0aWFsbHkgaW5mbHVlbmNlZCBieSBob3cgd2lkdGggc2V0dGluZyBvZiB0aGUgUlN0dWRpbyB3aW5kb3cuICAKCldlIGFyZSBpbnRlcmVzdGVkIGluIGEgc3VwcGxlbWVudGFyeSBUYWJsZSAzLiB3aGljaCBoYXMgbXVsdGlwbGUgcGFnZXMgYW5kIGluY2x1ZGVzIHRoZSBzYW1lIGhlYWRlciBvbiBlYWNoIHBhZ2U7IHdlIGNhbiB1c2UgdGhhdCB0byBkZXRlcm1pbmUgd2hhdCBlbGVtZW50cyBvZiBvdXIgcGRmX29iZXNpdHkgY2hhcmFjdGVyIHN0cmluZ3MgaW5jbHVkZSBvdXIgdGFibGUuIFdlIHdpbGwgdXNlIHRoZSBgc3RyX2RldGVjdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gc2VhcmNoIGZvciB0aGUgZWxlbWVudHMgdGhhdCBjb250YWluIHRleHQgdGhhdCBpcyBjb25zaXN0ZW50bHkgaW4gdGhlIGhlYWRlci4gVGhlIG91dHB1dCBvZiBvZiB0aGlzIGZ1bmN0aW9uIHdpbGwgc2hvdyB3aGljaCBlbGVtZW50cyBvZiB0aGUgb2JqZWN0IChpbiB0aGlzIGNhc2UgcGFnZXMgb2YgdGhlIHBkZikgaW5jbHVkZSB0aGlzIHBhdHRlcm4gaW5kaWNhdGVkIGFzIGEgIlRSVUUiIG9yICJGQUxTRSIuCgpgYGB7cn0Kc3RyaW5ncjo6c3RyX2RldGVjdChwYXR0ZXJuID0gIkFnZS1zdGFuZGFyZGlzZWQgbWVhbiBCTUkiLCBzdHJpbmcgPSBwZGZfb2Jlc2l0eSkKIyAiQWdlLXN0YW5kYXJkaXNlZCBtZWFuIEJNSSIgaXMgcGFydCBvZiB0aGUgaGVhZGVyIGluIHRoZSB0YWJsZSBvbiBldmVyeSBwYWdlIGluIHRoZSBwZGYuIAojIFRoaXMgc2hvd3MgdGhlIHBhZ2VzIHRoYXQgY29udGFpbiBvdXIgdGFibGUgb2YgaW50ZXJlc3QgKGFzIFRSVUUgdmFsdWVzKS4KYGBgCgpMZXQncyBleHRyYWN0IGp1c3QgdGhlIGRhdGEgZm9yIHRoZSB0YWJsZSBub3cgYW5kIGNhbGwgaXQgcnVyYWxfdXJiYW4uCmBgYHtyfQpydXJhbF91cmJhbiA8LXBkZl9vYmVzaXR5W3N0cmluZ3I6OnN0cl9kZXRlY3QocGF0dGVybiA9IkFnZS1zdGFuZGFyZGlzZWQgbWVhbiBCTUkiLCBzdHJpbmcgPXBkZl9vYmVzaXR5KV0KCnN0cihydXJhbF91cmJhbikgCiMgVGhlIHN0cigpIGZ1bmN0aW9uIGlzIHNpbWlsYXIgdG8gdGhlIHN1bW1hcnkgZnVuY3Rpb24KIyBUaGlzIHNob3dzIHVzIHRoYXQgdGhlcmUgYXJlIDEwIHBhZ2VzIHdvcnRoIG9mIGVsZW1lbnRzIGluIG91ciBydXJhbF91cmJhbiBvYmplY3QKCmBgYAoKCkxldCdzIGNoZWNrIHRoZSBmaXJzdCBhbmQgbGFzdCBwYWdlOgoKYGBge3IsIGV2YWw9RkFMU0V9CmNhdChydXJhbF91cmJhblsxXSkgCiMgVXNpbmcgdGhlIGNhdCgpIGZ1bmN0aW9uIHdoaWNoIHN0YW5kcyBmb3IgQ29uY2F0ZW5hdGUgQW5kIFByaW50IAojIFRoaXMgd2lsbCBhbGxvdyBmb3IgdGhlICJcbiIgdmFsdWVzIHRvIGJlIHNob3duIGFzIHNwYWNlcwpgYGAKCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJmaXJzdF9wYWdlX2luX1IucG5nIikpCmBgYAoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImZpcnN0X3BhZ2UucG5nIikpCmBgYAoKVGhpcyBsb29rcyB0aGUgc2FtZSBhcyB0aGUgYmVnaW5uaW5nLi4uIGhvdyBhYm91dCB0aGUgZW5kPwoKYGBge3IsIGV2YWwgPUZBTFNFfQpjYXQocnVyYWxfdXJiYW5bMTBdKQpgYGAKCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJsYXN0X3BhZ2VfaW5fUi5wbmciKSkKYGBgCgoKYGBge3IsIGVjaG8gPSBGQUxTRSB9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImxhc3RfcGFnZS5wbmciKSkKYGBgCgoKR3JlYXQhIE91ciBydXJhbF91cmJhbiBvYmplY3QgbG9va3MgbGlrZSBpdCBjb250YWlucyB0aGUgZW50aXJlIFN1cHBsZW1lbnRhcnkgMyB0YWJsZSwgYXMgYm90aCB0aGUgYmVnaW5uaW5nIGFuZCB0aGUgZW5kIGluY2x1ZGUgdGhlIGRhdGEgd2UgZXhwZWN0ZWQuCgojIyBEYXRhIFdyYW5nbGluZwoKQXQgdGhpcyBwb2ludCB3ZSBoYXZlIGxhcmdlIHN0cmluZ3Mgbm93IGZvciBlYWNoIHBhZ2Ugb2YgdGhlIHRhYmxlLCBidXQgdGhpcyBpcyBub3QgdmVyeSBjb252ZW5pZW50IHRvIHdvcmsgd2l0aC4gTm93IHdlIHdpbGwgd3JhbmdsZSB0aGUgZGF0YSBpbnRvIGEgbW9yZSB1c2FibGUgZm9ybS4gSWRlYWxseSB3ZSB3b3VsZCBsaWtlIG91ciBkYXRhIHRvIGJlIGluIHNvbWUgc29ydCBvZiB0YWJ1bGFyIGZvcm0uCgojIyMgU2VwYXJhdGUgdGhlIGRhdGEgaW50byBsaW5lcwoKRmlyc3QgaXQgd291bGQgYmUgdXNlZnVsIHRvIHNlcGFyYXRlIGVhY2ggcGFnZSBpbnRvIGxpbmVzLgpgYGB7cn0KcnVyYWxfdXJiYW4gPC1yZWFkcjo6cmVhZF9saW5lcyhydXJhbF91cmJhbikKc3RyKHJ1cmFsX3VyYmFuKSAKIyBub3cgd2UgaGF2ZSA0NjEgbGluZXMKcnVyYWxfdXJiYW5bNl0gCiMgd2UgY2FuIHNlZSB0aGF0IGxpbmUgNiBzaG93cyB0aGUgZGF0YSBmb3IgZmVtYWxlcyBpbiBBZmdoYW5pc3RhbiAgCmBgYAoKIyMjIFJlbW92aW5nIGV4Y2VzcyB3aGl0ZS1zcGFjZQoKV2UgYWxzbyBoYXZlIGEgbG90IG9mIHdoaXRlLXNwYWNlLi4uIGxldCdzIGdldCByaWQgb2YgdGhlIGV4Y2VzcyB3aGl0ZSBzcGFjZXMgdXNpbmcgYHN0cl9zcXVpc2goKWAuCgpgYGB7cn0KcnVyYWxfdXJiYW48LXN0cmluZ3I6OnN0cl9zcXVpc2gocnVyYWxfdXJiYW4pIApoZWFkKHJ1cmFsX3VyYmFuKQpgYGAKCk5vdyBpdCBpcyBtdWNoIGVhc2llciB0byBzZWUgdGhlIGRhdGEuCgpJZiB3ZSBsb29rIGF0IHRoZSBlbmQgb2YgdGhlIGZpcnN0IHBhZ2Ugb2YgdGhlIHRhYmxlIGFuZCB0aGUgc3RhcnQgb2YgdGhlIHNlY29uZCB3ZSBjYW4gc2VlIHRoYXQgdGhlIGhlYWRlciBpbmZvcm1hdGlvbiBpcyByZXBlYXRlZCwgYXMgd2VsbCBhcyBhIGxpbmUgd2l0aCB0aGUgcGFnZSBudW1iZXIgYW5kIGFuIGVtcHR5IGxpbmUsIGFuZCBhIGxpbmUgdGhhdCBzYXlzICIyIDIiLgpgYGB7cn0KcnVyYWxfdXJiYW5bNDQ6NTZdCmBgYAoKQWx0aG91Z2ggdGhlIGhlYWRlciB3YXMgbmVjZXNzYXJ5IG9uIGFsbCBvZiB0aGUgcGFnZXMgb2YgdGhlIHBkZiB2ZXJzaW9uIG9mIHRoZSB0YWJsZSwgd2Ugb25seSBuZWVkIHRoYXQgaW5mb3JtYXRpb24gb25jZSBpbiBvdXIgZGF0YS4KCiMjIyBSZW1vdmluZyB1bm5lY2Vzc2FyeSByZXBlYXRlZCBoZWFkZXIgaW5mb3JtYXRpb24KClNvLCBsZXQncyByZW1vdmUgYWxsIHRoZSBoZWFkZXIgaW5mb3JtYXRpb24gYW5kIHRoZSBwYWdlIG51bWJlciBsaW5lcyBmcm9tIHRoZSBydXJhbF91cmJhbiBvYmplY3QsIHRoZW4gd2Ugd2lsbCBtYWtlIGEgc2luZ2xlIGxpbmUgaGVhZGVyIGZvciB0aGUgYmVnaW5uaW5nLgpPbmUgd2F5IHRvIGRvIHRoaXMgaXMgdG8gZmluZCBhbGwgbGluZXMgdGhhdCBpbmNsdWRlIGVpdGhlciAid29tZW4iIG9yICJtZW4iIGFuZCBvbmx5IGtlZXAgdGhpcyBkYXRhLgpgYGB7cn0Kc3RyaW5ncjo6c3RyX3doaWNoKHN0cmluZyA9IHJ1cmFsX3VyYmFuLCBwYXR0ZXJuID0gIldvbWVufE1lbiIpIAojIEhlcmUgdGhlICJ8IiBpbmRpY2F0ZXMgdGhhdCB3ZSBhcmUgbG9va2luZyBmb3IgZWl0aGVyIHRoZSAiV29tZW4iIG9yICJNZW4iIHBhdHRlcm5zCmBgYAoKT0ssIHNvIHRoaXMgbG9va3MgY29ycmVjdC4gVGhpcyBpbmNsdWRlcyBtb3N0IGxpbmVzIGJ1dCB0aGVyZSBhcmUgZ2FwcyB3aGVyZSBhcmUgaGVhZGVyIGlzIGxvY2F0ZWQuCgpgYGB7cn0KcnVyYWxfdXJiYW4gPC0gcnVyYWxfdXJiYW5bc3RyX3doaWNoKHN0cmluZyA9IHJ1cmFsX3VyYmFuLCBwYXR0ZXJuID0gIldvbWVufE1lbiIpXQpgYGAKCldlIGNhbiBjaGVjayBvdXIgZGF0YSBub3cgdXNpbmcgZWl0aGVyIGhlYWQoKSBvciBnbGltcHNlKCkuCmBgYHtyfQpkcGx5cjo6Z2xpbXBzZShydXJhbF91cmJhbikKYGBgCgpgYGB7cn0KaGVhZChydXJhbF91cmJhbikKYGBgCgpTbyB0aGUgYGhlYWQoKWAgZnVuY3Rpb24gc2hvd3MgdXMgdGhlIGZpcnN0IHJvd3Mgb3IgbGluZXMgb2YgdGhlIGRhdGEsIHdoaWxlIHRoZSBgZ2xpbXBzZSgpYCBmdW5jdGlvbiBwcm92aWRlcyB1cyBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdG90YWwgc2l6ZSBvZiB0aGUgb2JqZWN0IGFuZCBzaG93cyB1cyB0aGUgZmlyc3QgbGluZSBvciByb3cuCgpHcmVhdCEgU28gbm93IG91ciBkYXRhIGxvb2tzIG11Y2ggYmV0dGVyIGJ1dCB3ZSBuZWVkIHRvIGFkZCBiYWNrIG91ciBoZWFkZXIgYW5kIHdlIHdvdWxkIGxpa2UgdGhpcyB0byBvbmx5IGJlIGEgc2luZ2xlIGxpbmUgdG8gbWFrZSBpdCBlYXN5IHRvIHRyYW5zZm9ybSBvdXIgZGF0YSBpbnRvIGEgdGFibGUgb3IgdGFibGUtbGlrZSBvYmplY3QuCgpgYGB7ciwgZWNobyA9IEZBTFNFfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJsYXN0X3BhZ2UucG5nIikpCmBgYAoKIyMjIERlYWxpbmcgd2l0aCBzcGFjaW5nCgpGaXJzdCBsZXQncyB0cnkgc3BsaXR0aW5nIG91ciBoZWFkZXItbGVzcyBkYXRhIGludG8gY29sdW1ucyBiYXNlZCBvbiBzcGFjZXM6CmBgYHtyfQooc3RyX3NwbGl0KHJ1cmFsX3VyYmFuLCAiICIsIHNpbXBsaWZ5ID0gVFJVRSkpWzE6MTAsXSAKIyBIZXJlIHdlIHdpbGwgdGFrZSBhIGxvb2sgYXQganVzdCB0aGUgZmlyc3QgMTAgbGluZXMKYGBgCgpUaGlzIGFsbW9zdCB3b3JrZWQsIGJ1dCB1bmZvcnR1bmF0ZWx5IGNvdW50cnkgbmFtZXMgdGhhdCBoYXZlIHNwYWNlcyB3aWxsIGJlIGEgcHJvYmxlbS4gV2UgY2FuIHNlZSB0aGF0IEFtZXJpY2FuIFNhbW9hIGhhcyBiZWVuIGRpdmlkZWQgaW50byB0d28gY29sdW1ucyBhbmQgYWxsIHN1YnNlcXVlbnQgY29sdW1ucyBhcmUgc2hpZnRlZC4KCgpTbyBub3cgbGV0J3MgdHJ5IHRvIGV4dHJhY3QgdGhlIGNvdW50cnkgaW5mb3JtYXRpb24sIGJ5IHNlcGFyYXRpbmcgdGhlIGNvdW50cnkgaW5mb3JtYXRpb24gZnJvbSB0aGUgc2V4IGluZm9ybWF0aW9uIHdoZW4gdGhlIHNleCBpcyBmZW1hbGUuIFNleCBhbHdheXMgc3RhcnRzIHdpdGggZWl0aGVyIGEgY2FwaXRhbCAiVyIgaWYgdGhlIGdlbmRlciBpcyBmZW1hbGUuIFdlIG5lZWQgdG8gdXNlIGEgc3BhY2UgYmVmb3JlIHRoZSAiVyIgb3RoZXJ3aXNlIHdlIHdpbGwgc3BsaXQgc29tZSBvZiB0aGUgY291bnRyeSBuYW1lcyBpZiB0aGUgbmFtZXMgc3RhcnRzIHdpdGggIlciLiBIZXJlIHdlIHdpbGwgYWxzbyBpbnRyb2R1Y2UgdGhlIGNvbmNlcHQgb2YgcGlwaW5nLCB3aGljaCB1c2VzIHRoZSBgJT4lYC4gVGhpcyBpcyByZWFsbHkgdXNlZnVsIHdoZW4gd2UgaGF2ZSBtdWx0aXBsZSBzdGVwcywgd2hpY2ggd2Ugd2lsbCBzaG93IHNvb24uCmBgYHtyfQoKV29tZW4gPC0gc3RyaW5ncjo6c3RyX3N1YnNldChzdHJpbmcgPSBydXJhbF91cmJhbiwgcGF0dGVybiA9ICJXb21lbiIpIAojIEZpcnN0IGxldCdzIHN1YnNldCB0aGUgZGF0YSB0byBvbmx5IHRoZSBsaW5lcyB0aGF0IGNvbnRhaW4gIldvbWVuIgoKY291bnRyeV9zcGxpdCA8LVdvbWVuICU+JQogIHN0cmluZ3I6OnN0cl9zcGxpdChwYXR0ZXJuPSAiIFciKSAlPiUKICB1bmxpc3QoKSAKCgpoZWFkKGNvdW50cnlfc3BsaXQpCmBgYAoKTm93IHdlIGNhbiBzZWUgdGhhdCBDb3VudHJ5IGlzIGFsd2F5cyB0aGUgb2RkIHJvd3MgYW5kIHRoZSByZXN0IG9mIHRoZSBkYXRhIGlzIHRoZSByZXN0IG9mIHRoZSByb3dzCgpgYGB7cn0KY291bnRyeSA8LWRhdGEuZnJhbWUoY291bnRyeV9zcGxpdCkgJT4lIAogIGRwbHlyOjpmaWx0ZXIocm93X251bWJlcigpICUlIDIgPT0gMSkgCmBgYAoKV2UgY2FuIHRha2UgYSBsb29rIHRvIG1ha2Ugc3VyZSB0aGF0IGFsbCB0aGUgY291bnRyeSBuYW1lcyBsb29rIGFzIGV4cGVjdGVkOgpgYGB7ciwgZXZhbD0gRkFMU0V9CmNvdW50cnkKYGBgCgojIyMjIHsuc2Nyb2xsYWJsZSB9CmBgYHtyLCBlY2hvID0gRkFMU0V9CmNvdW50cnkKYGBgCiMjIyMKYGBge3J9CldvbWVuX0JNSSA8LWRhdGEuZnJhbWUoY291bnRyeV9zcGxpdCkgJT4lIAogIGRwbHlyOjpmaWx0ZXIocm93X251bWJlcigpICUlIDIgPT0gMCkKYGBgCgpHcmVhdCEgTm93IHdlIGhhdmUgYSBsaXN0IG9mIHRoZSBjb3VudHJpZXMgdGhhdCBjYW4gYmUgdXNlZCBmb3IgYm90aCB0aGUgbWFsZSBhbmQgZmVtYWxlIGRhdGEuIAoKTGV0J3MgYWRkIHRoZSAiVyIgYmFjayB0byBvdXIgV29tZW4gZGF0YS4gV2UgY2FuIGRvIHNvIGJ5IHJlcGxhY2luZyB0aGUgc3RyaW5nICJvbWVuIiB3aXRoICJXb21lbiIgdXNpbmcgYHN0cl9yZXBhY2UoKWAuICAKYGBge3J9CmdsaW1wc2UoV29tZW4pCldvbWVuPC1Xb21lbl9CTUkgJT4lCm11dGF0ZShjb3VudHJ5X3NwbGl0ID1zdHJpbmdyOjpzdHJfcmVwbGFjZShzdHJpbmcgPWNvdW50cnlfc3BsaXQsIHBhdHRlcm4gPSJvbWVuIiwgcmVwbGFjZW1lbnQgPSAiV29tZW4iKSkKaGVhZChXb21lbiRjb3VudHJ5X3NwbGl0KQpgYGAKCkl0J3MgYWx3YXlzIGEgZ29vZCBpZGVhIHRvIGNoZWNrIHRoYXQgeW91ciBkYXRhIG9iamVjdHMgYXJlIHRoZSBzaXplIHlvdSBleHBlY3Qgd2hlbiB3cmFuZ2xpbmcuIFdlIGNhbiBkbyBzbyB3aXRoIHRoZSBgZGltKClgIGZ1bmN0aW9uLCB3aGljaCBzaG93cyB1cyB0aGUgZGltZW5zaW9ucyBvZiBkYXRhIG9iamVjdHMuCgpgYGB7cn0KZGltKFdvbWVuKQpgYGAKR3JlYXQhIFRoZXJlIGFyZSAyMDAgcm93cyBsaWtlIHdlIGV4cGVjdGVkLgoKTGV0J3MgZ3JhYiB0aGUgbWFsZSBkYXRhOgoKYGBge3J9CiMgcmVtZW1iZXIgb3VyIHJ1cmFsX3VyYmFuIG9iamVjdCBjb250YWlucyBtYWxlIGRhdGEgZm9yIHRoZSBvZGQgcm93cwoKTWVuIDwtZGF0YS5mcmFtZShydXJhbF91cmJhbikgJT4lIAogIGRwbHlyOjpmaWx0ZXIocm93X251bWJlcigpICUlIDIgPT0gMSkgCmhlYWQoTWVuJHJ1cmFsX3VyYmFuKQoKIyBBZ2FpbiBsZXQncyBtYWtlIHN1cmUgd2UgaGF2ZSB0aGUgY29ycmVjdCBudW1iZXIgb2Ygcm93cyBmb3Igb3VyIGZpbmFsICJNZW4iIGRhdGEgb2JqZWN0CgpkaW0oTWVuKSAKYGBgCkhvdyBhYm91dCBvdXIgbnVtYmVyIG9mIGNvbHVtbnM/IAoKSWYgd2UgdHJ5IHNwbGl0dGluZyBvdXIgZGF0YSBieSBzcGFjZSBhZ2Fpbiwgd2lsbCBpdCBoYXZlIHRoZSBleHBlY3RlZCBudW1iZXIgb2YgY29sdW1ucz8gV2hhdCBhYm91dCB0aGUgcm93cyB0aGF0IGNvbnRhaW4gbmEqIHZhbHVlcz8KYGBge3J9CiMgTGV0J3MganVzdCB0YWtlIHRoZSBNZW4gZGF0YSB0aGF0IGNvbnRhaW5zIG5hKiB2YWx1ZXMgLSB0aGlzIGNvbHVtbiBpcyBjYWxsZWQgcnVyYWxfdXJiYW4KdW5rbm93biA8LU1lbiAlPiVmaWx0ZXIoc3RyX2RldGVjdChwYXR0ZXJuID0ibmFcXCoiLCBzdHJpbmcgPSBydXJhbF91cmJhbikpIAoKIyBOb3cgd2UgY2FuIHRyeSBzcGxpdHRpbmcgYnkgYSBzcGFjZQp0aWJibGU6OmFzX3RpYmJsZShzdHJfc3BsaXQodW5rbm93biRydXJhbF91cmJhbiwgIiAiLCBzaW1wbGlmeSA9IFRSVUUpKQoKYGBgCgojIyMgRGVhbGluZyB3aXRoIE5BIHZhbHVlcwoKU28gY2xvc2UhIE5vdGljZSB0aGF0IHRoZSAibmEqIiB2YWx1ZXMgIGhhdmUgc2hpZnRlZCB0aGUgc3Vic2VxdWVudCB2YWx1ZXMgd2l0aGluIHRoZSBjb2x1bW5zIGJlY2F1c2UgdHlwaWNhbGx5IHRoZXJlIGlzIGEgc3BhY2UgYmV0d2VlbiB0aGUgQk1JIGFuZCB0aGUgY3JlZGlibGUgaW50ZXJ2YWxzLiBIZXJlIHdlIGNhbiBzZWUgdGhpcyBkYXRhIGluIG91ciBvcmlnaW5hbCBwZGY6CgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjEwMCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJtaXNzaW5nX3BkZi5wbmciKSkKYGBgCgpXZSBuZWVkIHRvIHJlcGxhY2Ugb3VyIG5hKiB2YWx1ZXMgIHdpdGggc29tZXRoaW5nIHRoYXQgaW5jbHVkZXMgYSBzcGFjZSBzbyB0aGF0IHdoZW4gd2Ugc2VwYXJhdGUgb3VyIGRhdGEgYnkgc3BhY2Ugd2Ugd2lsbCBoYXZlIHR3byB2YWx1ZXMgaW5zdGVhZCBvZiBvbmUgd2hlbiB3ZSBoYXZlIGFuIG5hKiAuIFRoZXJlZm9yZSwgbmEqIG5hKiBzaG91bGQgd29yay4KCmBgYHtyfQpjbGFzcyhNZW4kcnVyYWxfdXJiYW4pCiMgSW4gb3JkZXIgdG8gdXNlIHRoZSBmdW5jdGlvbnMgd2l0aGluIHRoZSBzdHJpbmdyIHBhY2thZ2UsIG91ciBNZW4gZGF0YSBuZWVkcyB0byBiZSBvZiBjaGFyYWN0ZXIgY2xhc3MKTWVuPC1hcy5jaGFyYWN0ZXIoTWVuJHJ1cmFsX3VyYmFuKSAKIyBUaGlzIGZ1bmN0aW9uIGFsbG93cyB1cyB0byBjaGFuZ2UgdGhlIGZhY3RvciBkYXRhIHdpdGhpbiBNZW4kcnVyYWxfdXJiYW4gdG8gdGhlIGNoYXJhY3RlciBjbGFzcwojIFdlIGFyZSBjaGFuZ2luZyB0aGUgc3RydWN0dXJlIHNvIHRoYXQgdGhlIGRhdGEgaXMgZGlyZWN0bHkganVzdCBjYWxsZWQgTWVuIGFuZCBub3Qgd2l0aGluIGEgdmVjdG9yIGNhbGxlZCBydXJhbF91cmJhbgpNZW48LXN0cmluZ3I6OnN0cl9yZXBsYWNlX2FsbChzdHJpbmcgPSBNZW4sIHBhdHRlcm4gPSAibmFcXCoiLCByZXBsYWNlbWVudCA9ICJuYVxcKiBuYVxcKiIpIAojIFRoZSBcXCBhcmUgbmVjZXNzYXJ5IGJlY2F1c2UgdGhlICogaXMgYSBzcGVjaWFsIGNoYXJhY3RlciAKIyBUaGUgKiB3b3VsZCB0eXBpY2FsbHkgaW5kaWNhdGUgYW55IHBvc3NpYmxlIHZhbHVlLCBidXQgaGVyZSB3ZSBhY3R1YWxseSB3YW50IGEgIioiIGluc3RlYWQKIyBUaHVzIHRoZSBkb3VibGUgYmFja3NsYXNoIGRvZXMgdGhhdCBmb3IgdXMKIyBIZXJlIHdlIGFyZSByZXBsYWNpbmcgYWxsIG9jY3VyZW5jZXMgb2YgdGhlIG5hKiB2YWx1ZXMgKHRodXMgc3RyX3JlcGxhY2VfYWxsIGluc3RlYWQgb2Ygc3RyX3JlcGxhY2UpIHdpdGggbmEqIG5hKi4gCgojIFRvIGNoZWNrIHRoYXQgdGhpcyB3b3JrZWQuLi4KTWVuWzIwOjMwXQojWUFZIQoKCiMgTm93IGZvciB0aGUgV29tZW4gZGF0YSBvYmplY3QKY2xhc3MoV29tZW4kY291bnRyeV9zcGxpdCkKIyB0aGUgZmVtYWxlIGRhdGEgaXMgYWxyZWFkeSBpbiBjaGFyYWN0ZXIgZm9ybQpXb21lbjwtc3RyaW5ncjo6c3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9IFdvbWVuJGNvdW50cnlfc3BsaXQsIHBhdHRlcm4gPSAibmFcXCoiLCByZXBsYWNlbWVudCA9ICJuYVxcKiBuYVxcKiIpIApXb21lblsyMDozMF0KCmBgYAoKCkdyZWF0LCBub3cgd2UgY2FuIHNwbGl0IG91ciBkYXRhIGJ5IHNwYWNlcy4KCiMjIyBTcGxpdHRpbmcgdGhlIGRhdGEKCgpgYGB7cn0KTWVuIDwtdGliYmxlOjphc190aWJibGUoc3RyX3NwbGl0KE1lbiwgIiAiLCBzaW1wbGlmeSA9IFRSVUUpKQojIE5vdGUgaGVyZSB3ZSBuZWVkIHRvIHVzZSB0aGUgY29sdW1uIG9mIFdvbWVuIHRoYXQgaGFzIHRoZSBkYXRhCmhlYWQoTWVuKQpXb21lbjwtYXNfdGliYmxlKHN0cl9zcGxpdChXb21lbiwgIiAiLCBzaW1wbGlmeSA9IFRSVUUpKQojIE5vdGUgaGVyZSB3ZSBuZWVkIHRvIHVzZSB0aGUgY29sdW1uIG9mIFdvbWVuIHRoYXQgaGFzIHRoZSBkYXRhCmhlYWQoV29tZW4pCldvbWVuWzIwOjMwLF0gCiMgV2UgY2FuIHNlZSB0aGF0IG91ciBuYSB2YWx1ZXMgbG9vayBjb3JyZWN0CmBgYAoKIyMjIEFkZGluZyBuZXcgaGVhZGVyCgpXZSBjYW4gc2VlIGZyb20gb3VyIHBkZiBhbmQgb3VyIG9iamVjdCBjYWxsZWQgaGVhZGVyIHdoYXQgdGhlIGhlYWRlciB3YXMgbGlrZS4gTGV0J3MgYWxzbyBtYWtlIGEgbmV3IHNpbmdsZSBsaW5lIGhlYWRlciwgYnV0IGxldCdzIHdhaXQgdG8gYWRkIENvdW50cnk6CgpgYGB7cn0KI2hlYWRlcgpuZXdfaGVhZGVyIDwtYygiU2V4IiwiTmF0aW9uYWxfQk1JXzE5ODUiLCAiTmF0aW9uYWxfQk1JXzE5ODVfQ0kiLCAiUnVyYWxfQk1JXzE5ODUiLCAiUnVyYWxfQk1JXzE5ODVfQ0kiLCAiVXJiYW5fQk1JXzE5ODUiLCAiVXJiYW5fQk1JXzE5ODVfQ0kiLCAiTmF0aW9uYWxfQk1JXzIwMTciLCAiTmF0aW9uYWxfQk1JXzIwMTdfQ0kiLCJSdXJhbF9CTUlfMjAxNyIsICJSdXJhbF9CTUlfMjAxN19DSSIsICJVcmJhbl9CTUlfMjAxNyIsICJVcmJhbl9CTUlfMjAxN19DSSIpCmBgYAoKCkxldCdzIGNoYW5nZSB0aGUgbmFtZXMgb2Ygb3VyIGNvbHVtbnMgb2Ygb3VyIHRpYmJsZSB0byB0aGlzIG5ldyBoZWFkZXIgZm9yIG91ciBNZW4gYW5kIFdvbWVuIGRhdGEKCmBgYHtyfQpuYW1lcyhXb21lbik8LW5ld19oZWFkZXIKbmFtZXMoTWVuKTwtbmV3X2hlYWRlcgpgYGAKCgpOb3cgd2Ugd2lsbCBhZGQgb3VyIGNvdW50cnkgZGF0YSB0byBib3RoIG91ciBNZW4gYW5kIFdvbWVuIHRpYmJsZXM6CgpgYGB7cn0KV29tZW4gPC0gZHBseXI6OmJpbmRfY29scyhjb3VudHJ5LCBXb21lbikKIyBUaGlzIHdpbGwgYWRkIHRoZSBjb3VudHJ5IGFzIGEgbmV3IGNvbHVtbiB0byB0aGUgV29tZW4gZGF0YSBvYmplY3Qgb24gdGhlIGxlZnQgCk1lbiA8LSBkcGx5cjo6YmluZF9jb2xzKGNvdW50cnksIE1lbikgCiMgVGhpcyB3aWxsIGFkZCB0aGUgY291bnRyeSBhcyBhIG5ldyBjb2x1bW4gdG8gdGhlIE1lbiBkYXRhIG9iamVjdCBvbiB0aGUgbGVmdCAKaGVhZChXb21lbikKYGBgCgojIyMgQ2hhbmdpbmcgdmFyaWFibGUgbmFtZXMKSGVyZSB3ZSB3aWxsIGNoYW5nZSB0aGUgdmFyaWFibGUgbmFtZSBvZiB0aGUgY291bnRyeSBkYXRhIHRvIGNvdW50cnksIGN1cnJlbnRseSBpdCBpcyBjYWxsZWQgY291bnRyeV9zcGxpdC4gSGVyZSB3ZSB3aWxsIGFsc28gaW50cm9kdWNlIHRoZSBjb25jZXB0IG9mIHRoZSBhc3NpZ25tZW50IHBpcGUuIEluIHRoaXMgY2FzZSBvdXIgcGlwZSBvcGVyYXRvciBsb29rcyBsaWtlIHRoaXMgYCU8PiVgIC4gIFVzaW5nIHRoaXMgZmFuY2llciBwaXBlIHJlcXVpcmVzIGFub3RoZXIgcGFja2FnZSwgIGNhbGxlZCBgbWFncml0dHJgLiBUaGUgb3RoZXIgc2ltcGxlciBwaXBlIG9wdGlvbnMgZnJvbSB0aGlzIHBhY2thZ2UgYXJlIGxvYWRlZCB3aXRoIGB0aWR5dmVyc2VgIChpZiB5b3UgdXNlZCBgbGlicmFyeSh0aWR5dmVyc2UpYCB3aGljaCBsb2FkcyBtb3N0IHRpZHl2ZXJzZSBwYWNrYWdlcyksIGJ1dCBub3QgdGhpcyBmYW5jaWVyIHZlcnNpb24uIAoKVGhlIGA+YCBwb3J0aW9uIG9mIHRoZSBwaXBlIHN0aWxsIGJlaGF2ZXMgbGlrZSBhIG5vcm1hbCBwaXBlLCB3aGlsZSB0aGUgYDxgIHBvcnRpb24gb2YgdGhlIHBpcGUgbWFrZXMgYW4gYXNzaWdubWVudCB0byB3aGF0ZXZlciB0aGUgYDxgaXMgcG9pbnRpbmcgdG8sIGp1c3QgbGlrZSB3aGVuIHdlIHVzZSB0aGUgdHlwaWNhbCBhc3NpZ25tZW50IG9wZXJhdG9yIGA8LWAuIAoKYGBge3J9CiMgbGlicmFyeShtYWdyaXR0cikgCiMgV2UgY2FuJ3QgdXNlIHRoZSBgJTw+JWAgdW5sZXNzIHdlIGxvYWQgdGhlIG1hZ3JpdHRyIHBhY2thZ2UKIyBXZSBoYXZlIGFscmVhZHkgZG9uZSB0aGlzIGJ1dCB3ZSBpbmNsdWRlIHRoaXMgZm9yIGlsbHVzdHJhdGl2ZSBwdXJwb3Nlcy4KIyBIZXJlIHdlIHdpbGwganVzdCB1c2UgdGhlIHRyYWRpdGlvbmFsIGFzc2lnbm1lbnQgc3RyYXRlZ3kKCldvbWVuPC1yZW5hbWUoV29tZW4sIENvdW50cnkgPSBjb3VudHJ5X3NwbGl0KSAKIyBXZSBoYXZlIHJlbmFtZWQgdGhlIGNvdW50cnlfc3BsaXQgdmFyaWFibGUgdG8gYmUgY2FsbGVkIENvdW50cnkKCiMgSGVyZSB3ZSByZWFzc2lnbiBNZW4gdXNpbmcgdGhlIHBpcGUgc3RyYXRlZ3kKTWVuICU8PiVyZW5hbWUoQ291bnRyeSA9IGNvdW50cnlfc3BsaXQpIAojIFdlIGhhdmUgcmVuYW1lZCB0aGUgY291bnRyeV9zcGxpdCB2YXJpYWJsZSB0byB0byBiZSBjYWxsZWQgY291bnRyeQojIFdlIGhhdmUgYWxzbyByZWFzc2lnbmVkIE1lbiB0byB0aGUgZGF0YSBvYmplY3Qgd2hpY2ggaGFzIHRoZSBjb3VudHJ5IHZhcmlhYmxlIHJlbmFtZWQKYGBgCgoKIyMjIEpvaW5pbmcgdGhlIGRhdGEKCk5vdyB3ZSBjYW4gY29tYmluZSBvdXIgTWVuIGFuZCBXb21lbiBkYXRhIHVzaW5nIHRoZSBgZnVsbF9qb2luKClgIGZ1bmN0aW9uIG9mIGBkcGx5cmAuIFRoaXMgd2lsbCBwdXQgYWxsIHRoZSBmZW1hbGUgZGF0YSBmaXJzdCAoeCkgYW5kIGFsbCB0aGUgbWFsZSBkYXRhIHNlY29uZCAoeSkuCgoKYGBge3J9CkJNSTwtZHBseXI6OmZ1bGxfam9pbih4ID0gTWVuLCB5ID0gV29tZW4pCiMgTGV0J3MgY2hlY2sgdGhlIHNpemUgb2Ygb3VyIEJNSSBkYXRhLi4uIGl0IHNob3VsZCBoYXZlIDQwMCByb3dzIChvYnMpLgpzdHIoQk1JKQpgYGAKCiMjIyBTb3J0aW5nIHRoZSBkYXRhCgpOb3cgTGV0cyBzb3J0IHRoZSBkYXRhIGJ5IGNvdW50cnk6CgpgYGB7cn0KQk1JIDwtZHBseXI6OmFycmFuZ2UoQk1JLCBDb3VudHJ5KQpoZWFkKEJNSSkKCmBgYAoKT3VyIGRhdGEgaXMgbG9va2luZyBncmVhdCEgTm93IHdlIG1pZ2h0IHdhbnQgdG8gbWFrZSBzdXJlIHRoYXQgb3VyIG9ic2VydmF0aW9ucyBmb3IgZWFjaCB2YXJpYWJsZSBsb29rIHRoZSB3YXkgd2Ugd2FudC4gSW4gb3RoZXIgd29yZHMgaWYgd2Ugd2FudCB0byBtYWtlIHBsb3RzIGFib3V0IE5hdGlvbmFsIEJNSSBpbiAxOTg1IHRoZW4gd2Ugd291bGQgbmVlZCBvdXIgdmFsdWVzIHRvIGJlIG51bWVyaWMuIExvb2tpbmcgYXQgb3VyIEJNSSBkYXRhIHVzaW5nIGBzdHIoKWAsIHdlIGNhbiBzZWUgdGhlIHR5cGUgb2YgZGF0YSBmb3IgZWFjaCBvZiBvdXIgdmFyaWFibGVzIGxpc3RlZCBqdXN0IGFmdGVyIHZhcmlhYmxlIG5hbWUgYW5kIHRoZSAiOiIgY29sb24uIExvb2tzIGxpa2Ugbm9uZSBvZiBvdXIgQk1JIGRhdGEgaXMgYWN0dWFsbHkgbnVtZXJpYywgYnV0IG9mIHRoZSBjbGFzcyBjaGFyYWN0ZXIuIExldCdzIGNoYW5nZSB0aGF0IG5vdy4KCmBgYHtyLCB3YXJuaW5nPUZBTFNFLCBldmFsfQpzdHIoQk1JKQpgYGAKV2UgY291bGQgY2hhbmdlIHRoZXNlIHZhbHVlcyB0byBiZSBudW1lcmljIHdpdGggNiBsaW5lcyBvZiBjb2RlIGxpa2UgdGhpczoKYGBge3IsIGV2YWwgPSBUUlVFfQpCTUkkTmF0aW9uYWxfQk1JXzE5ODUlPD4lIGFzLm51bWVyaWMKQk1JJFJ1cmFsX0JNSV8xOTg1JTw+JSBhcy5udW1lcmljCkJNSSRVcmJhbl9CTUlfMTk4NSU8PiUgYXMubnVtZXJpYwoKQk1JJE5hdGlvbmFsX0JNSV8yMDE3JTw+JSBhcy5udW1lcmljCkJNSSRSdXJhbF9CTUlfMjAxNyU8PiUgYXMubnVtZXJpYwpCTUkkVXJiYW5fQk1JXzIwMTclPD4lIGFzLm51bWVyaWMKCiMgIEFuZCBpZiB3ZSBkaWQgdGhpcyB3ZSB3b3VsZCBzZWUgdGhlc2UgdmFyaWFibGVzIHNob3cgYXMgIm51bSIgd2hpY2ggc3RhbmRzIGZvciBudW1lcmljCnN0cihCTUkpCmBgYAoKT3Igd2UgY2FuIHVzZSBhIG1vcmUgYXV0b21hdGVkIHdheSB3aXRoIHRoZSBgbWFwKClgIGZ1bmN0aW9uIG9mIHRoZSBgcHVycnJgIHBhY2thZ2U6CmBgYHtyfQpCTUlfbnVtZXJpYyA8LSBhc190aWJibGUocHVycnI6Om1hcCgoQk1JICU+JSBzZWxlY3QoLW1hdGNoZXMoIkNJfFNleHxDb3VudHJ5IikpKSwgYXMubnVtZXJpYykpIAojIFRoZSBtYXAgZnVuY3Rpb24gb2YgdGhlIHB1cnJyIHBhY2thZ2UgYWxsb3dzIHVzIHRvIGFwcGx5IHRoZSBhcy5udW1lcmljKCkgZnVuY3Rpb24gdG8gYWxsIHRoZSBzZWxlY3RlZCBjb2x1bW5zIG9mIEJNSSAKIyBXZSBoYXZlIHNlbGVjdGVkIHRob3NlIHRoYXQgZG9udCBjb250YWluIENJLCBTZXgsIG9yIENvdW50cnkgaW4gdGhlIGNvbHVtbiBuYW1lIAojIElmIHlvdSBhcmUgZmFtaWxpYXIgd2l0aCBhcHBseSgpLCB0aGlzIGZ1bmN0aW9uIGlzIHZlcnkgc2ltaWxhcgpCTUlfbnVtZXJpYyAlPD4lIG11dGF0ZShDb3VudHJ5ID1CTUkkQ291bnRyeSwgU2V4ID1CTUkkU2V4KQpoZWFkKEJNSV9udW1lcmljKQpgYGAKCgpJdCBpcyBnZW5lcmFsbHkgdXNlZnVsIHRvIGdldCB0aGUgZGF0YSBpbiB3aGF0IGlzIGNhbGxlZCA8Yj5sb25nPC9iPiBmb3JtYXQgZm9yIG90aGVyIGFuYWx5c2VzLCBhbmQgcGFydGljdWxhcmx5IGZvciBwbG90dGluZy4gCgpGb3IgYSBtb3JlIGRldGFpbGVkIGRlc2NyaXB0aW9uIGFib3V0IHRoaXMsIHBsZWFzZSBzZWUgdGhpcyBbY2FzZSBzdHVkeV0oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL29jcy1oZWFsdGhleHBlbmRpdHVyZS9vY3MtaGVhbHRoZXhwZW5kaXR1cmUuaHRtbCkKClRvIGRvIHRoaXMgd2Ugd2lsbCB1c2UgdGhlIGBnYXRoZXIoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZToKYGBge3J9CkJNSV9sb25nIDwtdGlkeXI6OmdhdGhlcihkYXRhID1CTUlfbnVtZXJpYywga2V5ID0gY2xhc3NfQk1JLCB2YWx1ZSA9IEJNSSwgTmF0aW9uYWxfQk1JXzE5ODU6VXJiYW5fQk1JXzIwMTcsIGZhY3Rvcl9rZXkgPSBGQUxTRSkgCiMgVGhlIGRhdGEgdmFsdWUgaW5kaWNhdGVzIHdoYXQgZGF0YSB5b3Ugc3RhcnQgd2l0aAojIFRoZSBrZXkgaW5kaWNhdGVzIHRoZSBuZXcgbmFtZSBvZiB0aGUgY29sdW1uIHRoYXQgd2lsbCBub3cgY29udGlhbiBpbmZvcm1hdGlvbiBhYm91dCAgdGhlIHZhbHVlcyBvZiB0aGUgY29sdW1ucyB3ZSB3aWxsIHB1dCB0b2dldGhlcgojIFRoZSB2YWx1ZSBpcyB0aGUgbmFtZSBvZiB0aGUgY29sdW1uIGZvciB0aGUgdmFsdWVzIGZvciBhbGwgdGhlIGNvbHVtbnMgdGhhdCBhcmUgYmVpbmcgcHV0IHRvZ2V0aGVyCiMgVGhlICI6IiBjYW4gYmUgdXNlZCB0byBpbmRlbnRpZnkgdGhlIHN0YXJ0IGFuZCBlbmQgb2YgdGhlIGNvbHVtbiBuYW1lcyB0aGF0IHlvdSBhcmUgcHV0dGluZyB0b2dldGhlcgojIFRoZSBmYWN0b3Jfa2V5IHBhcmFtYXRlciBkZXRlcm1pbmVzIGlmIHRoZSBuZXdseSBjcmVhdGVkIGtleSBjb2x1bW4gc2hvdWxkIGJlIGV2YWx1YXRlZCBhcyBhIGZhY3RvciBvciBub3QKaGVhZChCTUlfbG9uZykKYGBgCgpJdCB3b3VsZCBiZSB1c2VmdWwgdG8gcGFyc2UgdGhlIDE5ODUgYW5kIHRoZSAyMDE3IGRhdGEuIFdlIGNhbiBkbyBzbyBieSBzZXBhcmF0aW5nIHRoZSBwYXJ0cyBvZiB0aGUgY2xhc3NfQk1JIGNvbHVtbiB1c2luZyB0aGUgYHNlcGFyYXRlKClgIGZ1bmN0aW9uIG9mIHRoZSBgdGlkeXJgIHBhY2thZ2UuCmBgYHtyfQpCTUlfbG9uZyU8PiUgdGlkeXI6OnNlcGFyYXRlKGNsYXNzX0JNSSwgYygiUmVnaW9uIiwgTkEsICJZZWFyIikpIAojIFdlIHdpbGwgc2VwYXJhdGUgdGhlIGNsYXNzX0JNSSBjb2x1bW4gb2YgdGhlIEJNSV9sb25nIHRpYmJsZSBiYXNlZCBvbiB0aGUgdW5kZXJzY29yZXMgYW5kIGNyZWF0ZSB0d28gbmV3IGNvbHVtbnMuCiMgVGhlIGZpcnN0IGNvbHVtbiB3aWxsIGJlIGNhbGxlZCBSZWdpb24gYW5kIHdpbGwgY29udGFpbiB0aGUgZmlyc3QgcGFydCBvZiB0aGUgY2xhc3NfQk1JIGRhdGEgYmVmb3JlIHRoZSBmaXJzdCB1bmRlcnNjb3JlCiMgVGhlIHNlY29uZCBjb2x1bW4gd2lsbCBiZSBjYWxsZWQgeWVhciBhbmQgd2lsbCBjb250YWluIHRoZSB0aGlyZCBwYXJ0IG9mIHRoZSBkYXRhIGJhc2VkIG9uIHRoZSBkaXZpc2lvbnMgb2YgdGhlIHVuZGVyc2NvcmUKIyBUaGUgbWlkZGxlIHBhcnQgb2YgdGhlIGNvbHVtbiB3aWxsIG5vdCBiZSB1c2VkIHRvIGNyZWF0ZSBhbnkgbmV3IGNvbHVtbnMKaGVhZChCTUlfbG9uZykKCiMgTGV0J3Mgc2VlIGhvdyB0aGUgZGltZW5zaW9ucyBvZiB0aGUgQk1JIGRhdGEgaGF2ZSBjaGFuZ2VkIG5vdyB0aGF0IGl0IGlzIGluIGxvbmcgZm9ybWF0OgoKZGltKEJNSV9udW1lcmljKQpkaW0oQk1JX2xvbmcpCgojIFF1ZXN0aW9uIG9wcG9ydHVuaXR5OiBXaHkgYXJlIHRoZXJlIG5vdyAyLDQwMCByb3dzPwpgYGAKCgpHcmVhdCEgb3VyIGRhdGEgaXMgdmVyeSB1c2FibGUgbm93IGluIHRoaXMgZm9ybWF0IQoKCiMjIERhdGEgRXhwbG9yYXRpb24KCk5vdyB0aGF0IG91ciBkYXRhIGlzIGNsZWFuIGFuZCBpbiBhIGZvcm1hdCB0aGF0IHdlIGNhbiB3b3JrIHdpdGgsIHdlIGNhbiBzdGFydCB0byB0YWtlIGEgbG9vayBhdCB0aGUgZGF0YSBhbmQgaG93IGRpZmZlcmVudCBncm91cHMgbWlnaHQgY29tcGFyZS4KClN0YXRpc3RpY2FsbHkgc3BlYWtpbmcgdGhlcmUgYXJlIHRlc3RzIHRoYXQgY2FuIGFsbG93IHVzIHRvIGV2YWx1YXRlIGlmIHRoZSBtZWFucyBvZiB0aGUgZ3JvdXBzIGFyZSBkaWZmZXJlbnQuIEZpcnN0IGxldCdzIHNlZSBob3cgb3VyIGRhdGEgbG9va3MgaW4gZ2VuZXJhbC4KCiMjIyBHZW5lcmFsIHN1bW1hcnkKCgpgYGB7cn0Kc3VtbWFyeShCTUlfbnVtZXJpYykKIyBXZSBjYW4gc2VlIHRoYXQgdGhlIG1lYW4gIEJNSSBlc3RpbWF0ZXMgYXJlIGxhcmdlciBpbiAyMDE3CiMgSXMgdGhpcyBhIG1lYW5pbmdmdWwgaW5jcmVhc2U/CmBgYAoKTGV0cyBsb29rIGF0IHRoZSBEYXRhIHNlcGFyYXRlbHkgYnkgZ2VuZGVyOgpgYGB7cn0KI1dvbWVuOgpCTUlfbnVtZXJpYyAlPiUgc3Vic2V0KFNleCA9PSAiV29tZW4iKSAlPiUgc3VtbWFyeSgpCgpgYGAKCmBgYHtyfQojTWVuCkJNSV9udW1lcmljICU+JSBzdWJzZXQoU2V4ID09ICJNZW4iKSAlPiUgc3VtbWFyeSgpCmBgYAoKSXQgbG9va3MgbGlrZSBtZWFuIEJNSXMgaGF2ZSBpbmNyZWFzZWQgaW4gYWxsIHJlZ2lvbnMgZm9yIGJvdGggbWVuIGFuZCB3b21lbi4gSXQgaXMgdW5jbGVhciB0aG91Z2ggaWYgdGhpcyBjaGFuZ2UgaXMgc3RhdGlzdGljYWxseSBzaWduaWZpY2FudC4KCiMjIyBEaXN0cmlidXRpb25zCgpJbiBvcmRlciB0byBhcHBseSBhIHN0YXRpc3RpY2FsIHRlc3QgdG8gY29tcGFyZSB0aGUgbWVhbnMsIG9uZSBvZiB0aGUgZmlyc3QgdGhpbmdzIHRoYXQgaXMgdXNlZnVsIHRvIGRvIGlzIHRvIHBsb3QgdGhlIGZyZXF1ZW5jeSBvZiB0aGUgZGlmZmVyZW50IHBvc3NpYmxlIHZhbHVlcy4gVGhpcyBpcyBjYWxsZWQgYSA8Yj5kaXN0cmlidXRpb248L2I+LiBUbyBkbyB0aGlzIHdlIGNhbiB1c2UgdGhlIGBoaXN0KClgIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhIGhpc3RvZ3JhbS4KCklmIHRoZSBkYXRhIHdlcmUgd2hhdCB3ZSBjYWxsIDxiPm5vcm1hbGx5IGRpc3RyaWJ1dGVkPC9iPiB0aGVuIHRoZSBkaXN0cmlidXRpb24gc2hvdWxkIGJlIGVxdWFsbHkgY2VudGVyZWQgYXJvdW5kIHRoZSBtZWFuIGFuZCB3b3VsZCBsb29rIHNvbWV0aGluZyBsaWtlIHRoaXM6CgpgYGB7cn0Kbm9ybV9CTUlfZXhfZGF0YSA8LSB0aWJibGUobm9ybV9kYXRhID1ybm9ybShuID0gMjAwLCBtZWFuID0gMjQpKQojIFRoZSBybm9ybSgpIGZ1bmN0aW9uIGFsbG93cyB1cyB0byBtYWtlIGEgdmVjdG9yIG9mIG5vcm1hbHkgZGlzdHJpYnV0ZWQgZGF0YSBjZW50ZXJlZCBhcm91bmQgdGhlIG1lYW4gb2YgMjQKaGVhZChub3JtX0JNSV9leF9kYXRhKQpoaXN0KG5vcm1fQk1JX2V4X2RhdGEkbm9ybV9kYXRhKQpgYGAKCkFsdGVybmF0aXZlbHkgd2UgY2FuIHBsb3QgdGhpcyB1c2luZyB0aGUgYGdlb21faGlzdCgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UuIFRoZSBbZ2dwbG90Ml0oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvKSBwYWNrYWdlIGNyZWF0ZXMgcGxvdHMgYnkgdXNpbmcgbGF5ZXJzLiBOb3RpY2UgaW4gdGhlIGZvbGxvd2luZyBjb2RlIGhvdyB0aGVpciBpcyBhIHBsdXMgc2lnbiBiZXR3ZWVuIHRoZSBgZ2dwbG90KClgIGZ1bmN0aW9uIGFuZCB0aGUgYGdlb21faGlzdG9ncmFtKClgIGZ1bmN0aW9uLiBXaXRoIGdncGxvdDIgd2Ugc2VsZWN0IHdoYXQgZGF0YSB3ZSB3b3VsZCBsaWtlIHRvIHBsb3QgdXNpbmcgdGhlIGZpcnN0IGZ1bmN0aW9uIChgZ2dwbG90KClgKSBhbmQgdGhlbiB3ZSBhZGQgb24gYWRkaXRpb25hbCBsYXllcnMgb2YgY29tcGxleGl0eS4gSW4gdGhpcyBjYXNlIHRoZSBgZ2VvbV9oaXN0cm9ncmFtKClgIGZ1bmN0aW9uIGluaXRpYXRlcyB0aGUgcGxvdHRpbmcgb2YgYSBoaXN0b2dyYW0gd2l0aCB0aGUgZGF0YSB0aGF0IHdhcyBpZGVudGlmaWVkIGluIHRoZSBgZ2dwbG90KClgIGZ1bmN0aW9uLiBXZSB3aWxsIHNlZSBsYXRlciBob3cgd2UgY2FuIGFkZCBtYW55IGxheWVycyB0byBwbG90cyB3aXRoIGBnZ3Bsb3QyYC4gRm9yIGFkZGl0aW9uYWwgaW5mb3JtYXRpb24gb24gdXNpbmcgZ2dwbG90Miwgc2VlIHRoaXMgW2Nhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtaGVhbHRoZXhwZW5kaXR1cmUvb2NzLWhlYWx0aGV4cGVuZGl0dXJlLmh0bWwpLgoKYGBge3J9Cgpub3JtX0JNSV9leF9kYXRhICU+JSBnZ3Bsb3QyOjpnZ3Bsb3QoYWVzKHggPSBub3JtX2RhdGEpKSArIGdncGxvdDI6Omdlb21faGlzdG9ncmFtKCkgCiMgV2UgYXJlIHVzaW5nIHRoZSBjb2x1bW4gY2FsbGVkIG5vcm1fZGF0YSB3aXRoaW4gdGhlIG5vcm1fQk1JX2V4X2RhdGEgZGF0YSBvYmplY3QKIyBXaXRoIGdncGxvdDIgd2UgbXVzdCBmaXJzdCBzcGVjaWZ5IHRoZSBkYXRhIHdlIGFyZSB1c2luZyB3aXRoIHRoZSBnZ3Bsb3QoKSBmdW5jdGlvbgojIFRoZSBnZW9tX2hpc3RvZ3JhbSgpIGZ1bmN0aW9uIHNwZWNpZmllcyB3aGF0IHR5cGUgb2YgcGxvdCB0byBjcmVhdGUKYGBgCgpMZXQncyBzZWUgaG93IG91ciBkYXRhIGxvb2tzOgpgYGB7cn0KQk1JX2xvbmclPiUgZ2dwbG90KGFlcyh4ID0gQk1JKSkgKyBnZW9tX2hpc3RvZ3JhbSgpIAoKYGBgCgpPSywgc28gdGhlIGRhdGEgbG9va3MgbGlrZSBpdCBpcyB3aGF0IHdlIGNhbGwgPGI+cmlnaHQgc2tld2VkPC9iPiBiZWNhdXNlIHRoZSB0YWlsIG9mIHRoZSBkaXN0cmlidXRpb24gaXMgbG9uZ2VyIG9uIHRoZSByaWdodCBzaWRlLCBidXQgaXQgbG9va3MgZmFpcmx5IG5vcm1hbGx5IGRpc3RyaWJ1dGVkLgoKSWYgd2UgcGFyc2Ugb3VyIGRhdGEsIHdoYXQgZG9lcyBpdCBsb29rIGxpa2U/IFRoZSBlYXNpZXN0IHdheSB0byBkbyB0aGlzIGlzIHRvIHVzZSBzb21lIG90aGVyIGZ1bmN0aW9ucyBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UsIHBhcnRpY3VsYXJseSB0aGUgYGZhY2V0X3dyYXAoKWAgZnVuY3Rpb24sIHdoaWNoIHdpbGwgYWxsb3cgdXMgdG8gbG9vayBhdCBkaWZmZXJlbmNlcyBpbiB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBCTUkgZGF0YSBieSB5ZWFyLCBnZW5kZXIsIGFuZCByZWdpb24uIFdlIGNhbiBzZXF1ZW50aWFsbHkgZGl2aWRlIG91ciBwbG90cyBieSBkZWVwZXIgbGV2ZWxzIHVzaW5nIG11bHRpcGxlIHZhcmlhYmxlcyBhbmQgdGhlIGArYCBwbHVzIHNpZ24gd2l0aGluIGBmYWNldF93cmFwKClgLgoKYGBge3IsIGV2YWwgPSBUUlVFfQpCTUlfbG9uZyAlPiUKICBnZ3Bsb3QoYWVzKHg9Qk1JKSkgKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfd3JhcCggfiBTZXgpCgpCTUlfbG9uZyAlPiUKICBnZ3Bsb3QoYWVzKHg9Qk1JKSkgKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfd3JhcCggfiBTZXggKyBZZWFyKSAKCkJNSV9sb25nICU+JQogIGdncGxvdChhZXMoeD1CTUkpKSArCiAgZ2VvbV9oaXN0b2dyYW0oKSArCiAgZmFjZXRfd3JhcCggfiBTZXggKyBZZWFyICsgUmVnaW9uKSAKCmBgYAojIyMgUXVhbnRpbGUgUXVhbnRpbGUgUGxvdHMKCkxldCdzIHVzZSBhIG1ldGhvZCBjYWxsZWQgcXVhbnRpbGUgcXVhbnRpbGUgcGxvdHRpbmcgdG8gZGV0ZXJtaW5lIGlmIHRoZSBkYXRhIGlzIGluZGVlZCBub3JtYWxseSBkaXN0cmlidXRlZC4gVGhlc2UgcGxvdHMgYXJlIGNhbGxlZCA8Yj5RUSBwbG90czwvYj4uIFRoaXMgbWV0aG9kIGFsbG93cyB1cyB0byB0ZXN0IHRoZSBmaXQgb2Yga25vd24gdGhlb3JldGljYWwgZGlzdHJpYnV0aW9ucyAobGlrZSB0aGUgbm9ybWFsIGRpc3RyaWJ1dGlvbikgd2l0aCBvdXIgb2JzZXJ2ZWQgZGlzdHJpYnV0aW9uLiBUbyBkbyB0aGlzIHdlIHdpbGwgcGxvdCB0aGUgcXVhbnRpbGVzIG9mIG91ciBkYXRhIG9uIHRoZSB5LWF4aXMgYW5kIHRoZSBxdWFudGlsZXMgb2YgdGhlIHRoZW9yZXRpY2FsIG5vcm1hbCBkaXN0cmlidXRpb24gb24gdGhlIHgtYXhpcy4gSWYgdGhlIHF1YW50aWxlcyBsaW5lIHVwIHRoZW4gd2UgY2FuIHNheSB0aGF0IG91ciBkYXRhIGlzIGZhaXJseSBub3JtYWwuIFdoYXQgZXhhY3RseSBpcyBhIDxiPnF1YW50aWxlPC9iPj8gVGhpcyBpcyBhIGRpdmlzaW9uIG9mIHRoZSBkYXRhIGRpc3RyaWJ1dGlvbiBpbnRvIHJvdWdobHkgZXF1YWwgcG9ydGlvbnMuCgpIZXJlIGlzIGFuIGV4YW1wbGUgb2YgYSBRUSBwbG90IGZvciB0aGUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQgZGF0YSB0aGF0IHdlIGp1c3QgY3JlYXRlZCB1c2luZyB0aGUgYHN0YXRfcXEoKWAgZnVuY3Rpb24gb2YgIHRoZSBgZ2dwbG90MmAgcGFja2FnZToKCmBgYHtyfQoKbm9ybV9CTUlfZXhfZGF0YSAlPiUKICBnZ3Bsb3QoYWVzKHNhbXBsZSA9bm9ybV9kYXRhKSkgKwogIHN0YXRfcXEoKSsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKQoKCgpgYGAKCkhlcmUgd2UgY2FuIHNlZSB0aGF0IHRoZSBxdWFudGlsZXMgYXJlIGZhaXJseSBzaW1pbGFyIGJldHdlZW4gdGhlIG9ic2VydmVkIGFuZCB0aGVvcmV0aWNhbCBkYXRhLiBXZSBzZWUgdGhhdCB0aGUgcG9pbnRzIG1vc3RseSBmYWxsIG9uIHRoZSBsaW5lLCBob3dldmVyIHRoZXJlIGFyZSBzb21lIHBvaW50cyB0aGF0IGFyZSBhIGJpdCBmdXJ0aGVyIGZyb20gdGhlIGxpbmUgYXMgd2UgZ2V0IHRvIHRoZSBleHRyZW1lIHF1YW50aWxlcy4gTm90aWNlIHRoYXQgdGhlIHNhbXBsZSBxdWFudGlsZXMgKHdoaWNoIHdpbGwgYmUgZmFpcmx5IHNpbWlsYXIgdG8gb3VyIHJlYWwgQk1JIGRhdGEgcXVhbnRpbGVzKSBvbiB0aGUgeS1heGlzIGhhcyB0aGUgc2FtZSByYW5nZSBhcyB0aGUgdmFsdWVzIHRoYXQgd2UgY3JlYXRlZC4gU28gdmFsdWVzIHRoYXQgYXJlIGJlbGxvdyAyMiBmb3IgZXhhbXBsZSBhcmUgcmVwcmVzZW50ZWQgYXMgdGhlIHBvaW50cyBiZWxsb3cgMjIgb24gdGhlIHktYXhpcy4gQXMgZXhwZWN0ZWQgd2Ugc2VlIHRoYXQgYWJvdXQgaGFsZiB0aGUgcG9pbnRzIGFyZSBiZWxsb3cgb3VyIG1lYW4gb2YgMjQuCgpJZiB3ZSB3ZXJlIHRvIHVzZSBkaWZmZXJlbnQgZGF0YSB0aGF0IGhhZCBhIHJhbmdlIG9mIGRpZmZlcmVudCB2YWx1ZXMgb3VyIHktYXhpcyB3b3VsZCBzaGlmdCBhY2NvcmRpbmcgdG8gdGhlIHJhbmdlIG9mIHZhbHVlcy4gRm9yIGV4YW1wbGUgdGhlIE9yYW5nZSBkYXRhIHdpdGhpbiB0aGUgaW5zdGFsbGF0aW9uIG9mIFIgaW5jbHVkZXMgZGF0YSBhYm91dCB0aGUgY2lyY3VtZmVyZW5jZSBvZiBvcmFuZ2UgdHJlZXMgaW4gbWlsbGltZXRlcnMuIEhlcmUgd2UgY2FuIHNlZSB0aGF0IHRoZSBxdWFudGlsZXMgYXJlIHF1aXRlIGRpZmZlcmVudCBidXQgcmVmbGVjdCB0aGUgcmFuZ2Ugb2Ygb3JhbmdlIHRyZWUgY2lyY3VtZmVyZW5jZXMuCmBgYHtyfQpyYW5nZShPcmFuZ2UkY2lyY3VtZmVyZW5jZSkKT3JhbmdlJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPWNpcmN1bWZlcmVuY2UpKSArCiAgc3RhdF9xcSgpKyAjIHRvIGFkZCB0aGUgbGluZSB3ZSBuZWVkIHRvIGFsc28gaW5jbHVkZSBzdGF0X3FxX2xpbmUoKQogIHN0YXRfcXFfbGluZSgpCmBgYAoKCkxldCdzIHRha2UgYSBsb29rIGF0IG91ciBCTUkgZGF0YToKCmBgYHtyfQoKQk1JX2xvbmcgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPUJNSSkpICsKICBzdGF0X3FxKCkrICMgdG8gYWRkIHRoZSBsaW5lIHdlIG5lZWQgdG8gYWxzbyBpbmNsdWRlIHN0YXRfcXFfbGluZSgpCiAgc3RhdF9xcV9saW5lKCkKYGBgCgpGb3IgdGhlIHNha2Ugb2Ygc2ltcGxpY2l0eSwgd2UgYXJlIGdvaW5nIHRvIGZvY3VzIG9uIHRoZSBkYXRhIGZyb20gdGhlIHdvbWVuLiAgVGhpcyBpcyBiZWNhdXNlIHdvbWVuIHdlcmUgaWRlbnRpZmllZCBpbiB0aGUgcGFwZXIgdG8gaGF2ZSBsYXJnZXIgaW5jcmVhc2VzIGluIEJNSS4gSWYgd2Ugd2FudCB0byBwZXJmb3JtIHRlc3RzIG9uIHRoZXNlIGdyb3VwcyBzcGVjaWZpY2FsbHksIHRoZW4gd2UgbmVlZCB0byBrbm93IGhvdyB0aGlzIGRhdGEgbG9va3MuCgpgYGB7cn0KCkJNSV9sb25nICU+JQogIGZpbHRlcihTZXggPT0gIldvbWVuIikgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPUJNSSkpICsKICBzdGF0X3FxKCkrICMgdG8gYWRkIHRoZSBsaW5lIHdlIG5lZWQgdG8gYWxzbyBpbmNsdWRlIHN0YXRfcXFfbGluZSgpCiAgc3RhdF9xcV9saW5lKCkKYGBgCgoKV2hhdCBhYm91dCBieSByZWdpb24gYW5kIHllYXI/IElmIHdlIGNvbXBhcmUgdGhlc2UgZGF0YSB0aGVuIHdlIG5lZWQgdG8gbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGVhY2ggb2YgdGhlc2Ugc3Vic2V0cy4KCmBgYHtyfQoKQk1JX2xvbmcgJT4lCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJSdXJhbCIpICU+JQogIGdncGxvdChhZXMoc2FtcGxlID1CTUkpKSArCiAgc3RhdF9xcSgpICsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKSArICMgdG8gYWRkIGEgdGl0bGUgd2UgY2FuIHVzZSBnZ3RpdGxlKCkKICBnZ3RpdGxlKCJRUSBQbG90IGZvciBXb21lbiAyMDE3IFJ1cmFsIERhdGEiKQoKQk1JX2xvbmcgJT4lCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJVcmJhbiIpICU+JQogIGdncGxvdChhZXMoc2FtcGxlID1CTUkpKSArCiAgc3RhdF9xcSgpICsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiUVEgUGxvdCBmb3IgV29tZW4gMjAxNyBVcmJhbiBEYXRhIikKCgpCTUlfbG9uZyAlPiUKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlJ1cmFsIikgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPUJNSSkpICsKICBzdGF0X3FxKCkgKyAjIHRvIGFkZCB0aGUgbGluZSB3ZSBuZWVkIHRvIGFsc28gaW5jbHVkZSBzdGF0X3FxX2xpbmUoKQogIHN0YXRfcXFfbGluZSgpICsKICBnZ3RpdGxlKCJRUSBQbG90IGZvciBXb21lbiAxOTg1IFJ1cmFsIERhdGEiKQoKQk1JX2xvbmcgJT4lCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpICU+JQogIGdncGxvdChhZXMoc2FtcGxlID1CTUkpKSArCiAgc3RhdF9xcSgpICsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiUVEgUGxvdCBmb3IgV29tZW4gMTk4NSBVcmJhbiBEYXRhIikKCgpgYGAKCldlIGNhbiBzZWUgdGhhdCBhdCB0aGUgZXh0cmVtZXMgb2Ygb3VyIHF1YW50aWxlcywgZm9yIG1vc3Qgb2Ygb3VyIGRhdGEsIG91ciB0YWlscyBhcmUgbm90IHZlcnkgc2ltaWxhciB0byB0aGUgdGhlb3JldGljYWwgZGlzdHJpYnV0aW9uLiBUaGUgUnVyYWwgZGF0YSBsb29rcyBtb3JlIG5vcm1hbCB0aGFuIHRoZSB1cmJhbiBkYXRhLCBidXQgaWYgd2Ugd2VyZSB0byB1c2Ugc3RhdGlzdGljYWwgdGVzdHMgdGhhdCByZWx5IG9uIG5vcm1hbGl0eSwgdGhpcyB3b3VsZCByZXF1aXJlIHRoYXQgYm90aCBncm91cHMgYXJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLgoKRmluYWxseSwgc29tZSBzdGF0aXN0aWNpYW5zIGFsc28gdXNlIHRoZSBTaGFwaXJvLVdpbGsgdGVzdCBmb3Igbm9ybWFsaXR5IHdoZW4gdGhlIFFRIHBsb3QgaXMgYSBiaXQgdW5jbGVhci4gTWFueSBzdGF0aXN0aWNpYW5zIGhvd2V2ZXIgd291bGQgY29uY2x1ZGUgZnJvbSB0aGUgUVEgcGxvdHMgdGhhdCBub3JtYWxpdHkgaGFzIGJlZW4gdmlvbGF0ZWQuCgojIyMgU2hhcGlyby1XaWxrIHRlc3QKCkZvciBpbGx1c3RyYXRpdmUgcHVycG9zZXMgd2Ugd2lsbCBzaG93IGhvdyB3ZSBjYW4gdXNlIHRoZSBgZHBseXJgIGBzdW1tYXJpemUoKWAgYW5kIGBncm91cF9ieSgpYCBmdW5jdGlvbnMgdG8gcGVyZm9ybSB0aGUgU2hhcGlyby1XaWxrIHRlc3QgZm9yIGFsbCB0aGUgc3Vic2V0cyB3ZSBhcmUgaW50ZXJlc3RlZCBpbi4KCmBgYHtyfQoKbm9ybV9CTUlfZXhfZGF0YSRub3JtX2RhdGEgJT4lIHNoYXBpcm8udGVzdCgpIAojIGV4YW1wbGUgb2YgdGhlIHRlc3Qgb3V0cHV0IGZvciBub3JtYWwgZGF0YQoKQk1JX2xvbmcgJT4lIAogIGZpbHRlcihTZXggPT0gIldvbWVuIikgJT4lIAogIGdyb3VwX2J5KFllYXIsIFJlZ2lvbikgJT4lIAogIHN1bW1hcml6ZShzaGFwaXJvX3Rlc3QgPSBzaGFwaXJvLnRlc3QoQk1JKSRwLnZhbHVlKQoKYGBgCgpXZSBzZWUgdGhhdCBhbGwgdGhlIGRhdGEgZG9lcyBub3QgYXBwZWFyIHRvIGJlIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLgoKIyMgRGF0YSBBbmFseXNpcwoKCldlIGFyZSBpbnRlcmVzdGVkIGluIGNvbXBhcmluZyB0aGUgbWVhbnMgb2YgZmVtYWxlIHJ1cmFsIGFuZCB1cmJhbiBCTUkgbWVhc3VyZW1lbnRzIGZvciBib3RoIHllYXJzLiBUaGVyZSBhcmUgdHdvIHBvc3NpYmxlIGNsYXNzZXMgb2Ygc3RhdGlzdGljYWwgdGVzdHMgdGhhdCB3ZSBjb3VsZCBydW4gdG8gY29tcGFyZSB0aGUgbWVhbnMgb2YgdGhlc2UgdHdvIGdyb3VwczoKCjEpIFBhcmFtZXRyaWMKMikgbm9ucGFyYW1ldHJpYwoKIyMjIFBhcmFtZXRyaWMgdHdvIHNhbXBsZSBtZWFuIHRlc3RzCgpPZnRlbiB3aGVuIGNvbXBhcmluZyB0d28gZ3JvdXBzIHdlIG1pZ2h0IHBlcmZvcm0gYSB0d28gc2FtcGxlIHQgdGVzdCB0byBkZXRlcm1pbmUgaWYgdGhlIG1lYW5zIG9mIGVhY2ggZ3JvdXAgaXMgZGlmZmVyZW50LiBUaGUgdHdvIHNhbXBsZSB0IHRlc3QgaG93ZXZlciwgcmVsaWVzIG9uIHNldmVyYWwgYXNzdW1wdGlvbnM6CgoxKSBUaGUgZGF0YSBmb3IgYm90aCBncm91cHMgaXMgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKMikgVGhlIHZhcmlhbmNlIG9mIGJvdGggZ3JvdXBzIGlzIHNpbWlsYXIKCklmIHRoZXNlIGFzc3VtcHRpb25zIGFyZSB2aW9sYXRlZCwgdGhpcyBkb2Vzbid0IG5lY2Vzc2FyaWx5IG1lYW4gd2UgY2FuJ3QgcGVyZm9ybSBhIHQgdGVzdC4gSXQganVzdCBtZWFucyB3ZSBtYXkgaGF2ZSB0byB0cmFuc2Zvcm0gdGhlIGRhdGEgdG8gbWFrZSBpdCBub3JtYWxseSBkaXN0cmlidXRlZCBhbmQgd2UgbWF5IG5lZWQgdG8gcGVyZm9ybSB0aGUgdCB0ZXN0IGluIGEgc3BlY2lhbCB3YXkgdG8gYWNjb3VudCBmb3IgdGhlIGRpZmZlcmVuY2UgaW4gdGhlIHZhcmlhbmNlIGluIHRoZSB0d28gZ3JvdXBzLiBBbHRlcm5hdGl2ZWx5LCB3ZSBjYW4gdXNlIGEgbm9ucGFyYW1ldHJpYyB0ZXN0IGxpa2UgdGhlIFdpbGNveG9u4oCTTWFubuKAk1doaXRuZXkgKFdNVykgdGVzdC4gV2Ugd2lsbCBleHBsb3JlIGJvdGggb2YgdGhlc2Ugb3B0aW9ucy4KClRoZSB0IHRlc3QgaXMgYWxzbyBmYWlybHkgcm9idXN0IHRvIG5vbi1ub3JtYWxpdHkgaWYgdGhlIGRhdGEgaXMgcmVsYXRpdmVseSBsYXJnZSwgYW5kIHdlIGhhdmUgYW4gbiBvZiAyMDAsIHdoaWNoIHNob3VsZCBiZSBzdWZmaWNpZW50IGJ1dCBsZXQncyBpbnZlc3RpZ2F0ZSB0aGUgbm9ucGFyYW1ldHJpYyB0ZXN0cyBmdXJ0aGVyLiAKCgpPZnRlbiB3ZSB3b3VsZCBjaGVjayBpZiB0aGUgdmFyaWFuY2Ugb2YgdGhlIHJ1cmFsIGFuZCB1cmJhbiBkYXRhIGlzIGVxdWFsIHVzaW5nIHRoZSBgdmFyLnRlc3QoKWAgZnVuY3Rpb24uIEhvd2V2ZXIgdGhpcyBpcyBhbiBGIHRlc3QgYW5kIGFzc3VtZXMgdGhhdCB0aGUgZGF0YSBpcyBub3JtYWxseSBkaXN0cmlidXRlZC4gSW5zdGVhZCB3ZSB3aWxsIHVzZSB0aGUgYG1vb2QudGVzdCgpYCBmdW5jdGlvbiB3aGljaCBwZXJmb3JtcyB0aGUgTW9vZCdzIHR3by1zYW1wbGUgdGVzdCBmb3IgYSBkaWZmZXJlbmNlIGluIHNjYWxlIHBhcmFtZXRlcnMgYW5kIGRvZXMgbm90IGFzc3VtZSB0aGF0IHRoZSBkYXRhIGlzIG5vcm1hbGx5IGRpc3RyaWJ1dGVkLgoKYGBge3J9CgoKbW9vZC50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgQk1JKSwgCiAgICAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlVyYmFuIiksIEJNSSkpCiMgbm90IGVxdWFsIC0gcCB2YWx1ZSA8LjA1IHJlamVjdCB0aGUgbnVsbDogbm8gZGlmZmVyZW5jZSBpbiB0aGUgdmFyaWFuY2Ugb2YgdGhlIGRpc3RyaWJ1dGlvbnMKCm1vb2QudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSksIAogICAgICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpKQojIG5vdCBlcXVhbCAtIHAgdmFsdWUgPC4wNSwgcmVqZWN0IHRoZSBudWxsOiBubyBkaWZmZXJlbmNlIGluIHRoZSB2YXJpYW5jZSBvZiB0aGUgZGlzdHJpYnV0aW9ucwoKbW9vZC50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMTk4NSIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgQk1JKSwgCiAgICAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSkpCiMgZXF1YWwgLSBwIHZhbHVlID4uMDUsIGFjY2VwdCB0aGUgbnVsbDogbm8gZGlmZmVyZW5jZSBpbiB0aGUgdmFyaWFuY2Ugb2YgdGhlIGRpc3RyaWJ1dGlvbnMKCm1vb2QudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlVyYmFuIiksIEJNSSksIAogICAgICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpKQojIGVxdWFsIC0gcCB2YWx1ZSA+LjA1LCBhY2NlcHQgdGhlIG51bGw6IG5vIGRpZmZlcmVuY2UgaW4gdGhlIHZhcmlhbmNlIG9mIHRoZSBkaXN0cmlidXRpb25zCgpgYGAKCk91ciBwIHZhbHVlIGlzIGxlc3MgdGhhbiAuMDUgZm9yIGJvdGggdGVzdHMsIHRodXMgd2UgcmVqZWN0IG91ciBudWxsIGh5cG90aGVzaXMgdGhhdCB0aGVyZSBpcyBubyBkaWZmZXJlbmNlIGluIHRoZSB2YXJpYW5jZS4gVGhlcmVmb3JlLCB3ZSBjb25jbHVkZSB0aGF0IHRoZSB2YXJpYW5jZSBpcyBub3QgZXF1YWwgYW5kIHRoYXQgb3VyIGRhdGEgYWxzbyB2aW9sYXRlcyB0aGlzIGFzc3VtcHRpb24uCgpXZSB3aWxsIHBlcmZvcm0gYSBzcGVjaWFsIHQudGVzdCB3aGVyZSB3ZSBhY2NvdW50IGZvciB0aGUgZmFjdCB0aGF0IG91ciB2YXJpYW5jZSBpcyBub3QgZXF1YWwuIAoKQW5vdGhlciBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbiBpcyB0aGF0IHRoZSBkYXRhIGlzIHdoYXQgd2UgY2FsbCA8Yj5wYWlyZWQ8L2I+LiBNZWFuaW5nIHRoZSBtZWFzdXJlbWVudHMgZnJvbSB0aGUgcnVyYWwgYW5kIHVyYmFuIGFyZWFzIGFyZSBub3QgaW5kZXBlbmRlbnQuIFRoYXQgaXMgYmVjYXVzZSB3ZSBoYXZlIGEgcnVyYWwgYW5kIHVyYmFuIG1lYXN1cmVtZW50IG1lYW4gZm9yIG5lYXJseSBldmVyeSBjb3VudHJ5LiBUaHVzIHRoZXNlIHZhbHVlcyBtYXkgYmUgbW9yZSBzaW1pbGFyIHRvIG9uZSBhbm90aGVyIGlmIHRoZXkgY29tZSBmcm9tIHRoZSBzYW1lIGNvdW50cnkuCgpgYGB7cn0KCnQudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSksIAogICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLCAKICAgICAgIHZhci5lcXVhbCA9IEZBTFNFLCBwYWlyZWQgPSBUUlVFKQojIG1lYW5zIGFyZSBkaWZmZXJlbnQgLSBwIHZhbHVlIDwuMDUgcmVqZWN0IHRoZSBudWxsOiBubyBkaWZmZXJlbmNlIGluIHRoZSBtZWFucwoKdC50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMTk4NSIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgQk1JKSwgCiAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlVyYmFuIiksIEJNSSksCiAgICAgICB2YXIuZXF1YWwgPSBGQUxTRSwgcGFpcmVkID0gVFJVRSkKIyBtZWFucyBhcmUgZGlmZmVyZW50IC0gcCB2YWx1ZSA8LjA1IHJlamVjdCB0aGUgbnVsbDogbm8gZGlmZmVyZW5jZSBpbiB0aGUgbWVhbnMKCnQudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSksIAogICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJSdXJhbCIpLCBCTUkpLAogICAgICAgdmFyLmVxdWFsID0gRkFMU0UsIHBhaXJlZCA9IFRSVUUpCiMgbWVhbnMgYXJlIGRpZmZlcmVudCAtIHAgdmFsdWUgPC4wNSByZWplY3QgdGhlIG51bGw6IG5vIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW5zCgp0LnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLCAKICAgICAgIHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiVXJiYW4iKSwgQk1JKSwKICAgICAgIHZhci5lcXVhbCA9IEZBTFNFLCBwYWlyZWQgPSBUUlVFKQojIG1lYW5zIGFyZSBkaWZmZXJlbnQgLSBwIHZhbHVlIDwuMDUgcmVqZWN0IHRoZSBudWxsOiBubyBkaWZmZXJlbmNlIGluIHRoZSBtZWFucwoKYGBgCgoKTm93IHdlIHdpbGwgdHJ5IHRyYW5zZm9ybSBvdXIgZGF0YSB0byBtYWtlIGl0IG1vcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIE9uZSB3YXkgdG8gZG8gdGhpcyBpcyB0byB0YWtlIHRoZSBsb2dhcml0aG0gb2YgdGhlIGRhdGEgdmFsdWVzLiBUaGVuIHdlIHdpbGwgc2VlIGhvdyB0aGlzIGluZmx1ZW5jZXMgdGhlIHJlc3VsdHMuCgpgYGB7cn0KCiMgY3JlYXRlIGEgbmV3IGNvbHVtbiB3aXRoIHRoZSBsb2cgdmVyc2lvbiBvZiB0aGUgQk1JIHZhcmlhYmxlCkJNSV9sb25nX2xvZyA8LSBtdXRhdGUoQk1JX2xvbmcsIGxvZ19CTUk9bG9nKHB1bGwoQk1JX2xvbmcsQk1JKSkpIAoKCkJNSV9sb25nX2xvZyAlPiUKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlJ1cmFsIikgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPWxvZ19CTUkpKSArCiAgc3RhdF9xcSgpICsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiUVEgUGxvdCBmb3IgTG9nIFdvbWVuIDIwMTcgUnVyYWwgRGF0YSIpCgpCTUlfbG9uZ19sb2cgJT4lCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJVcmJhbiIpICU+JQogIGdncGxvdChhZXMoc2FtcGxlID1sb2dfQk1JKSkgKwogIHN0YXRfcXEoKSArICMgdG8gYWRkIHRoZSBsaW5lIHdlIG5lZWQgdG8gYWxzbyBpbmNsdWRlIHN0YXRfcXFfbGluZSgpCiAgc3RhdF9xcV9saW5lKCkgKwogIGdndGl0bGUoIlFRIFBsb3QgZm9yIExvZyBXb21lbiAyMDE3IFVyYmFuIERhdGEiKQoKCkJNSV9sb25nX2xvZyAlPiUKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlJ1cmFsIikgJT4lCiAgZ2dwbG90KGFlcyhzYW1wbGUgPWxvZ19CTUkpKSArCiAgc3RhdF9xcSgpICsgIyB0byBhZGQgdGhlIGxpbmUgd2UgbmVlZCB0byBhbHNvIGluY2x1ZGUgc3RhdF9xcV9saW5lKCkKICBzdGF0X3FxX2xpbmUoKSArCiAgZ2d0aXRsZSgiUVEgUGxvdCBmb3IgTG9nIFdvbWVuIDE5ODUgUnVyYWwgRGF0YSIpCgpCTUlfbG9uZ19sb2cgJT4lCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpICU+JQogIGdncGxvdChhZXMoc2FtcGxlID1sb2dfQk1JKSkgKwogIHN0YXRfcXEoKSArICMgdG8gYWRkIHRoZSBsaW5lIHdlIG5lZWQgdG8gYWxzbyBpbmNsdWRlIHN0YXRfcXFfbGluZSgpCiAgc3RhdF9xcV9saW5lKCkgKwogIGdndGl0bGUoIlFRIFBsb3QgZm9yIExvZyBXb21lbiAxOTg1IFVyYmFuIERhdGEiKQoKCkJNSV9sb25nX2xvZyAlPiUgCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iKSAlPiUgCiAgZ3JvdXBfYnkoWWVhciwgUmVnaW9uKSAlPiUgCiAgc3VtbWFyaXplKHNoYXBpcm9fdGVzdCA9IHNoYXBpcm8udGVzdChsb2dfQk1JKSRwLnZhbHVlKQoKIyByZWNhbGwgd2hhdCBpdCB3YXMgYmVmb3JlCkJNSV9sb25nICU+JSAKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIpICU+JSAKICBncm91cF9ieShZZWFyLCBSZWdpb24pICU+JSAKICBzdW1tYXJpemUoc2hhcGlyb190ZXN0ID0gc2hhcGlyby50ZXN0KEJNSSkkcC52YWx1ZSkKCiMgc28gdGhlIGRhdGEgaXMgbW9yZSBub3JtYWwuLi4gYnV0IHN0aWxsIG5vdCByZWFsbHkgbm9ybWFsbHkgZGlzdHJpYnV0ZWQKCmBgYAoKTGV0J3Mgc2VlIHRoZSByZXN1bHRzIG9mIHRoZSB0IHRlc3Qgd2l0aCB0aGUgdHJhbnNmb3JtZWQgZGF0YToKYGBge3J9Cgp0LnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmdfbG9nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgbG9nX0JNSSksIAogICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmdfbG9nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiVXJiYW4iKSwgbG9nX0JNSSksIAogICAgICAgdmFyLmVxdWFsID0gRkFMU0UsIHBhaXJlZCA9IFRSVUUpCiMgbWVhbnMgYXJlIGRpZmZlcmVudCAtIHAgdmFsdWUgPC4wNSByZWplY3QgdGhlIG51bGw6IG5vIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW5zCgp0LnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmdfbG9nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMTk4NSIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgbG9nX0JNSSksIAogICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmdfbG9nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMTk4NSIsIFJlZ2lvbiA9PSAiVXJiYW4iKSwgbG9nX0JNSSksCiAgICAgICB2YXIuZXF1YWwgPSBGQUxTRSwgcGFpcmVkID0gVFJVRSkKIyBtZWFucyBhcmUgZGlmZmVyZW50IC0gcCB2YWx1ZSA8LjA1IHJlamVjdCB0aGUgbnVsbDogbm8gZGlmZmVyZW5jZSBpbiB0aGUgbWVhbnMKCnQudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZ19sb2csIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJSdXJhbCIpLCBsb2dfQk1JKSwgCiAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZ19sb2csIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJSdXJhbCIpLCBsb2dfQk1JKSwKICAgICAgIHZhci5lcXVhbCA9IEZBTFNFLCBwYWlyZWQgPSBUUlVFKQojIG1lYW5zIGFyZSBkaWZmZXJlbnQgLSBwIHZhbHVlIDwuMDUgcmVqZWN0IHRoZSBudWxsOiBubyBkaWZmZXJlbmNlIGluIHRoZSBtZWFucwoKdC50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nX2xvZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlVyYmFuIiksIGxvZ19CTUkpLCAKICAgICAgIHB1bGwoZmlsdGVyKEJNSV9sb25nX2xvZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlVyYmFuIiksIGxvZ19CTUkpLAogICAgICAgdmFyLmVxdWFsID0gRkFMU0UsIHBhaXJlZCA9IFRSVUUpCiMgbWVhbnMgYXJlIGRpZmZlcmVudCAtIHAgdmFsdWUgPC4wNSByZWplY3QgdGhlIG51bGw6IG5vIGRpZmZlcmVuY2UgaW4gdGhlIG1lYW5zCgpgYGAKClRoZSBkYXRhIGFwcGVhcnMgdG8gYmUgbW9yZSBzaW1pbGFyIHRvIHRoZSBub3JtYWwgZGlzdHJpYnV0aW9uLCBidXQgbW9zdCBzdWJzZXRzIHN0aWxsIGZhaWwgdGhlIFNoYXBpcm8tV2lsayBub3JtYWxpdHkgdGVzdC4gQWdhaW4sIG91ciBzYW1wbGUgc2l6ZSBvZiAyMDAgaXMgcXVpdGUgbGFyZ2UgYW5kIHRoZSB0IHRlc3QgaXMgZ2VuZXJhbGx5IHF1aXRlIHJvYnVzdCB0byB2aW9sYXRpb25zIG9mIG5vcm1hbGl0eSB3aXRoIGxhcmdlIG4sIHRodXMgdGhlIG1vZGlmaWVkIHQgdGVzdCB0byBhY2NvdW50IGZvciB1bmVxdWFsIHZhcmlhbmNlIG1pZ2h0IGJlIGEgZ29vZCBvcHRpb24gdXNpbmcgdGhlIGxvZyBub3JtYWxpemVkIGRhdGEsIGFzIGl0IGlzIGF0IGxlYXN0IG1vcmUgbm9ybWFsbHkgZGlzdHJpYnV0ZWQuIEhvd2V2ZXIsIGxldCdzIHRha2UgYSBsb29rIGF0IG5vbiBwYXJhbWV0cmljIHRlc3RzLCB3aGljaCBhcmUgYWxzbyBhIGdyZWF0IG9wdGlvbiB3aGVuIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgdCB0ZXN0IGFyZSB2aW9sYXRlZC4gCgojIyMgTm9ucGFyYW1ldHJpYyB0d28gc2FtcGxlIG1lYW4gdGVzdHMKClRoZXJlIGFyZSB0d28gb3B0aW9ucyB0byBjb25zaWRlciB3aGVuIHRoZSBhc3N1bXB0aW9ucyBvZiB0aGUgdCB0ZXN0IGFyZSB2aW9sYXRlZC4gVGhlIFdpbGNveG9uIHNpZ25lZCByYW5rIHRlc3QgYW5kIHRoZSBUd28tc2FtcGxlIEtvbG1vZ29yb3YtU21pcm5vdiB0ZXN0IGJvdGggZG8gbm90IGFzc3VtZSBub3JtYWxpdHkuIFRodXMgdGhlc2UgdGVzdHMgc2hvdWxkIGJlIGNvbnNpZGVyZWQgd2hlbiB0aGUgZGF0YSBvZiBlaXRoZXIgZ3JvdXBzIGRvZXMgbm90IGFwcGVhciB0byBiZSBub3JtYWxseSBkaXN0cmlidXRlZCBhbmQgcGFydGljdWxhcmx5IHdoZW4gdGhlIG51bWJlciBvZiBzYW1wbGVzIGlzIGxvdy4KCkltcG9ydGFudGx5IHRoZSBLb2xtb2dvcm92LVNtaXJub3YgdGVzdCBkb2VzIG5vdCBhc3N1bWUgbm9ybWFsaXR5IG9yIGVxdWFsIHZhcmlhbmNlLCB3aGlsZSB0aGUgV2lsY294b24gc2lnbmVkIHJhbmsgdGVzdCBkb2VzIGFzc3VtZSBlcXVhbCB2YXJpYW5jZS4gSGVyZSBpcyBob3cgeW91IHdvdWxkIHBlcmZvcm0gdGhlc2UgdGVzdHMuIEhvd2V2ZXIgaW4gb3VyIGNhc2UsIGJlY2F1c2UgdGhlIHZhcmlhbmNlIGlzIG5vdCBlcXVhbCBiZXR3ZWVuIG91ciBncm91cHMgb2YgaW50ZXJlc3QsIHRoZSBLb2xtb2dvcm92LVNtaXJub3YgdGVzdCB3b3VsZCBiZSBtb3JlIGFwcHJvcHJpYXRlLgoKYGBge3J9Cgojd2lsY294LnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJSdXJhbCIpLCBCTUkpLCAKIyAgICAgICAgICAgIHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiVXJiYW4iKSwgQk1JKSwKIyAgICAgICAgICAgIHBhaXJlZCA9IFRSVUUpCiN3aWxjb3gudGVzdChwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSksIAojICAgICAgICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLAojICAgICAgICAgICAgcGFpcmVkID0gVFJVRSkpCgprcy50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMjAxNyIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgQk1JKSwgCiAgICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIyMDE3IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLAogICAgICAgIHBhaXJlZCA9IFRSVUUpCgprcy50ZXN0KHB1bGwoZmlsdGVyKEJNSV9sb25nLCBTZXggPT0gIldvbWVuIiwgWWVhciA9PSAiMTk4NSIsIFJlZ2lvbiA9PSAiUnVyYWwiKSwgQk1JKSwgCiAgICAgICAgcHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLAogICAgICAgIHBhaXJlZCA9IFRSVUUpCgpgYGAKCgojI1doYXQgYWJvdXQgdGhlIGRpZmZlcmVuY2UgaW4gZmVtYWxlIEJNSSBmcm9tIDE5ODUgdG8gMjAxNyBmb3IgYm90aCByZWdpb25zPwoKYGBge3J9CmtzLnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJSdXJhbCIpLCBCTUkpLCAKICAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlJ1cmFsIiksIEJNSSksCiAgICAgICAgcGFpcmVkID0gVFJVRSkKCmtzLnRlc3QocHVsbChmaWx0ZXIoQk1JX2xvbmcsIFNleCA9PSAiV29tZW4iLCBZZWFyID09ICIxOTg1IiwgUmVnaW9uID09ICJVcmJhbiIpLCBCTUkpLCAKICAgICAgICBwdWxsKGZpbHRlcihCTUlfbG9uZywgU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gPT0gIlVyYmFuIiksIEJNSSksCiAgICAgICAgcGFpcmVkID0gVFJVRSkKCmBgYAoKIyMgRGF0YSBWaXN1YWxpemF0aW9uCgpBZ2FpbiB3ZSB3aWxsIHV0aWxpemUgYGdncGxvdDJgIHRvIGNyZWF0ZSBwbG90cy5JZiB5b3UgbmVlZCBhZGRpdGlvbmFsIGluZm9ybWF0aW9uIHBsZWFzZSBzZWUgW2hlcmVdKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtaGVhbHRoZXhwZW5kaXR1cmUvb2NzLWhlYWx0aGV4cGVuZGl0dXJlLmh0bWwpLiBUaGUgdG9wIHR3byBsaW5lcyBvZiB0aGUgY29kZSBmb3IgdGhlIGZvbGxvd2luZyBwbG90cywgZmlsdGVyIHRoZSBkYXRhIHRvIG9ubHkgc3BlY2lmaWMgdmFsdWVzIG9mIGludGVyZXN0LiBUaGVuIHdlIGxheWVyIHdoYXQgaXMgY2FsbGVkIGEgaml0dGVyIG9uIHRvcCBvZiBhIGJveCBwbG90LiBBIGppdHRlciBpcyBlc3NlbnRpYWxseSBhIGRvdCBwbG90IGJ1dCB3aXRoIHNvbWUgdmFyaWF0aW9uIG9uIHRoZSBsb2NhdGlvbiBvZiB0aGUgcG9pbnRzIHNvIHRoYXQgdGhleSBkbyBub3QgbGluZSB1cCB2ZXJ0aWNhbGx5IHdoaWNoIGNhbiBtYWtlIHRoZSBpbmRpdmlkdWFsIHBvaW50cyBkaWZmaWN1bHQgdG8gc2VlLgoKTGV0J3MgbG9vayBhdCB0aGUgbmF0aW9uYWwgbWVhbiBCTUkgZXN0aW1hdGVzIGZvciBlYWNoIG9mIHRoZSB5ZWFyczoKYGBge3J9CkJNSV9sb25nICU+JSAKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjE5ODUiLCBSZWdpb24gIT0gIk5hdGlvbmFsIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gUmVnaW9uLCB5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IC4zKSAjIHRoZSB3aWR0aCBkZXRlcm1pbmVzIGhvdyB3aWRlIHRoZSBwb2ludHMgYXJlIHBsb3R0ZWQKCkJNSV9sb25nICU+JSAKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgPT0gIjIwMTciLCBSZWdpb24gIT0gIk5hdGlvbmFsIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gUmVnaW9uLCB5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IC4zKQoKYGBgCgpOb3cgTGV0J3MgbG9vayBhdCB0aGUgY2hhbmdlIGluIHJ1cmFsIGFuZCB1cmJhbiBtZWFuIEJNSSBlc3RpbWF0ZXM6CmBgYHtyfQpCTUlfbG9uZyAlPiUgCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyICVpbiUgYygiMTk4NSIsICIyMDE3IiksIFJlZ2lvbiA9PSAiUnVyYWwiKSAlPiUKICAjIGZpbHRlcmluZyB0aGlzIHdheSBhbGxvd3MgdXMgdG8ga2VlcCBkYXRhIGZyb20gYm90aCB5ZWFycwogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBCTUkpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGdlb21faml0dGVyKHdpZHRoID0gLjMpCgpCTUlfbG9uZyAlPiUgCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyICVpbiUgYygiMTk4NSIsICIyMDE3IiksIFJlZ2lvbiA9PSAiVXJiYW4iKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcih3aWR0aCA9IC4zKQoKYGBgCgpIb3cgZG8gdGhlIGRpZmZlcmVudCBjb3VudHJpZXMgY29tcGFyZT8gIE9yIGluIG90aGVyIHdvcmRzIHdoYXQgZG8gdGhlIGluZGl2aWR1YWwgZG90cyByZXByZXNlbnQgaW4gb3VyIGJveCBwbG90cz8KV2Ugd2lsbCB0YWtlIGEgbG9vayB1c2luZyBgZ2VvbV9sYWJlbCgpYDoKCmBgYHtyfQoKQk1JX2xvbmcgJT4lIAogIGZpbHRlcihTZXggPT0gIldvbWVuIiwgWWVhciAlaW4lIGMoIjE5ODUiLCAiMjAxNyIpLCBSZWdpb24gPT0gIlJ1cmFsIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgeSA9IEJNSSkpICsKICBnZW9tX2JveHBsb3QoKSArCiAgZ2VvbV9qaXR0ZXIod2lkdGggPSAuMykrCiAgZ2VvbV9sYWJlbChhZXMobGFiZWwgPSBDb3VudHJ5KSkKCmBgYAoKSWYgd2UgaW5jbHVkZSBhbGwgY291bnRyeSBuYW1lcyB0aGlzIGlzIGEgYml0IHRvbyBtdWNoLi4uIHNvIHBlcmhhcHMgd2Ugc2hvdWxkIGZvY3VzIG9uIGp1c3QgdGhlIGV4dHJlbWUgQk1JIHZhbHVlcyB1c2luZyBgZmlsdGVyKClgIGZ1bmN0aW9uIG9mIHRoZWBkcGx5cmAgcGFja2FnZS4gV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYGdncmVwZWxgIHBhY2thZ2UgdG8gaGF2ZSBvdXIgbGFiZWxzIG5vdCBvdmVybGFwIGVhY2ggb3RoZXIuCgoKYGBge3J9CgpCTUlfbG9uZyAlPiUgCiAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyICVpbiUgYygiMTk4NSIsICIyMDE3IiksIFJlZ2lvbiA9PSAiUnVyYWwiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gQk1JKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBnZW9tX2ppdHRlcihkYXRhPUJNSV9sb25nICU+JSAKICAgICAgICAgICAgICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgJWluJSBjKCIxOTg1IiwgIjIwMTciKSwgUmVnaW9uID09ICJSdXJhbCIpICU+JQogICAgICAgICAgICAgIGZpbHRlcihCTUk+MzEgfCBCTUk8MTkgfCBDb3VudHJ5ID09ICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiKSwgCiAgICAgICAgICAgICAgYWVzKHggPVllYXIsIHkgPUJNSSksCiAgICAgICAgICAgICAgd2lkdGggPSAuMDIpICsKICBnZ3JlcGVsOjpnZW9tX3RleHRfcmVwZWwoZGF0YT1CTUlfbG9uZyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyICVpbiUgYygiMTk4NSIsICIyMDE3IiksIFJlZ2lvbiA9PSAiUnVyYWwiKSAlPiUKICAgICAgICAgICAgICBmaWx0ZXIoQk1JPjMxIHwgQk1JPDE5IHwgQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiksIAogICAgICAgICAgICAgIGFlcyh4ID1ZZWFyLCB5ID1CTUksIGxhYmVsID0gQ291bnRyeSkpCiAgICAgICAgICAgICAgCiAgICAgICAgICAgICAgCmBgYAoKQW5kIGxldCdzIGZpbGwgdGhlIGJveCBwbG90cyB3aXRoIGNvbG9yIGFuZCBvdXRsaW5lIGluIGJsYWNrOgpgYGB7cn0KCkJNSV9sb25nICU+JSAKICBmaWx0ZXIoU2V4ID09ICJXb21lbiIsIFllYXIgJWluJSBjKCIxOTg1IiwgIjIwMTciKSwgUmVnaW9uID09ICJSdXJhbCIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIHkgPSBCTUkpKSArCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgY29sb3IgPSAiYmxhY2siLCBhZXMoZmlsbCA9IFllYXIpKSArCiAgZ2VvbV9qaXR0ZXIoZGF0YT1CTUlfbG9uZyAlPiUgCiAgICAgICAgICAgICAgZmlsdGVyKFNleCA9PSAiV29tZW4iLCBZZWFyICVpbiUgYygiMTk4NSIsICIyMDE3IiksIFJlZ2lvbiA9PSAiUnVyYWwiKSAlPiUKICAgICAgICAgICAgICBzdWJzZXQoQk1JPjMxIHwgQk1JPDE5IHwgQ291bnRyeSA9PSAiVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIiksIAogICAgICAgICAgICAgIGFlcyh4ID1ZZWFyLCB5ID1CTUkpLAogICAgICAgICAgICAgIHdpZHRoID0gLjAyKSArCiAgZ2dyZXBlbDo6Z2VvbV90ZXh0X3JlcGVsKGRhdGE9Qk1JX2xvbmcgJT4lIAogICAgICAgICAgICAgIGZpbHRlcihTZXggPT0gIldvbWVuIiwgWWVhciAlaW4lIGMoIjE5ODUiLCAiMjAxNyIpLCBSZWdpb24gPT0gIlJ1cmFsIikgJT4lCiAgICAgICAgICAgICAgc3Vic2V0KEJNST4zMSB8IEJNSTwxOSB8IENvdW50cnkgPT0gIlVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSIpLCAKICAgICAgICAgICAgICBhZXMoeCA9WWVhciwgeSA9Qk1JLCBsYWJlbCA9IENvdW50cnkpKQoKYGBgCgoKIyMjIE92ZXJhbGwgZGlmZmVyZW5jZXMKCkxldCdzIHRha2UgYSBsb29rIGF0IGFsbCB0aGUgZGF0YSB0b2dldGhlcjoKYGBge3J9CmdncGxvdChCTUlfbG9uZywgYWVzKHggPSBZZWFyLCB5ID0gQk1JLCBjb2wgPSBSZWdpb24pKSArIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGNvbG9yID0gImJsYWNrIiAsIGFlcyhmaWxsID0gUmVnaW9uKSkgKyBmYWNldF9ncmlkKH5TZXgpICAgCmBgYAoKVGhhdCdzIHVzZWZ1bCwgYnV0IGxldCdzIGxvb2sgYXQgdGhlIGluZGl2aWR1YWwgcG9pbnRzIGFuZCBpbmNsdWRlIG91ciBjb3VudHJ5IGxhYmVscywgdG8gZG8gc28gbGV0cyBjaGFuZ2Ugb3VyIFVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSBsYWJlbCB0byBVU0E6CmBgYHtyfQpCTUlfbG9uZyRDb3VudHJ5IDwtQk1JX2xvbmckQ291bnRyeSAlPiVzdHJfcmVwbGFjZSggcGF0dGVybiA9ICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCByZXBsYWNlbWVudCA9ICJVU0EiKQoKCmdncGxvdChCTUlfbG9uZywgYWVzKHggPSBZZWFyLCB5ID0gQk1JLCBjb2wgPSBZZWFyKSkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBjb2xvciA9ICJibGFjayIgLCBhZXMoZmlsbCA9IFllYXIpKSArIAogIGZhY2V0X2dyaWQoflNleCArIFJlZ2lvbikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MzAsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJyZWQiLCBzaXplID0xKSAgKyAKICAjIFRoaXMgd2lsbCBhZGQgYSBob3Jpem9udGFsIGRhc2hlZCBsaW5lIHRvIGluZGljYXRlIEJNSSB2YWx1ZXMgY29uc2lkZXJlZCB0byBiZSBpbiB0aGUgcmFuZ2Ugb2Ygb2Jlc2l0eQogIGdlb21faml0dGVyKGRhdGE9c3Vic2V0KEJNSV9sb25nKSwgYWVzKHggPVllYXIsIHkgPUJNSSksIHdpZHRoID0gLjIsIHNpemUgPTIsIHNoYXBlID0yMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImdyYXkiKSAgKyAKICAjIFRoaXMgd2lsbCBhZGQgdGhlIGluZGl2aWR1YWwgY291bnRyeSBkYXRhIHBvaW50cwogICMgVGhlIHNoYXBlIDIxIGFsbG93cyBmb3IgYSBkaWZmZXJlbnQgZmlsbCBhbmQgb3V0bGluZSBjb2xvciAoIHRoZSBvdXRsaW5lIGlzIHRoZSAiY29sb3IiKQogICMgVGhlIHdpZHRoIGRldGVybWluZXMgaG93IHdpZGUgdGhlIGppdHRlciBwb2ludHMgYXJlIHBsb3R0ZWQKICBnZW9tX2ppdHRlcihkYXRhPXN1YnNldChCTUlfbG9uZywgQ291bnRyeSA9PSAiVVNBIiksIGFlcyh4ID1ZZWFyLCB5ID1CTUkpLCB3aWR0aCA9IC4wMiwgc2l6ZSA9MTIsIHNoYXBlID0yMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImdyYXkiKSArIAogICMgVGhpcyB3aWxsIGFkZCBwb2ludHMgdGhhdCBhcmUgbGFyZ2VyIGZvciB0aGUgVVNBIGRhdGEKICBnZW9tX3RleHQoZGF0YT1zdWJzZXQoQk1JX2xvbmcsICBDb3VudHJ5ID09ICJVU0EiKSwgYWVzKHggPVllYXIsIHkgPUJNSSxsYWJlbD1Db3VudHJ5KSwgY29sb3IgPSAiYmxhY2siKSArIAogICMgVGhpcyB3aWxsIGFkZCBVU0EgbGFiZWxzIHRvIHRoZSBVU0EgcG9pbnRzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAjIFRoaXMgaXMgdXNlZnVsIGZvciByZW1vdmluZyB0aGUgbGVnZW5kCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGFuZ2xlID0gMzApLCAKICAgICAgICAjIHRoaXMgY2hhbmdlcyB0aGUgc2l6ZSBhbmQgYW5nbGUgb2YgdGhlIHggYXhpcyBwb2ludCBsYWJlbHMgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPTE1KSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE1KSwgCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpICsKICAjIFRoaXMgY2hhbmdlcyB0aGUgc2l6ZSBvZiB4IGF4aXMgbGFiZWxzIGZvciB0aGUgZmFjZXQgCiAgICAgICAgZ2d0aXRsZSggIkRpZmZlcmVuY2VzIGluIEJNSSBPdmVyIFRpbWUgYW5kIEFjcm9zcyBSZWdpb24gVHlwZSBhbmQgR2VuZGVyIikgIyBBZGQgYSAgcGxvdCB0aXRsZQogICAKCgpgYGAKCkhlcmUgd2UgY2FuIHNlZSB0aGF0IG92ZXJhbGwgQk1JIGFwcGVhcnMgdG8gYmUgaW5jcmVhc2luZyBnbG9iYWxseSBvdmVyIHRpbWUuIEFkZGl0aW9uYWxseSB3ZSBjYW4gc2VlIHRoYXQgdGhpcyBpcyBvY2N1cnJpbmcgbm90IGp1c3QgaW4gdXJiYW4gYXJlYXMsIGJ1dCBhbHNvIGluIHJ1cmFsIGFyZWFzLiBUaGUgVVMgaXMgY29uc2lzdGVudGx5IGFib3ZlIHRoZSBtZWRpYW4gaW4gYWxsIHN0cmF0YSBvZiB0aGUgZGF0YS4gSW4gZ2VuZXJhbCwgdGhlIGZlbWFsZSBkYXRhIHNob3dzIGhpZ2hlciBCTUkgdmFsdWVzIHRoYW4gdGhlIG1hbGUgZGF0YS4gVGhlIHJ1cmFsIFVTQSBCTUkgYXBwZWFycyB0byBiZSBoaWdoZXIgdGhhbiB0aGUgdXJiYW4gQk1JIGZvciBib3RoIG1lbiBhbmQgd29tZW4uIE1hbnkgY291bnRyaWVzIGhhdmUgYXZlcmFnZSBCTUkgZXN0aW1hdGVzIGFib3ZlIHRoZSBvYmVzaXR5IHRocmVzaG9sZCBvZiAzMC4gVGh1cyBpdCBhcHBlYXJzIHRoYXQgZWR1Y2F0aW9uIGFuZCBvdXRyZWFjaCBwcm9ncmFtcyBmb3Igd2VpZ2h0IG1hbmFnZW1lbnQgc2hvdWxkIGZvY3VzIG9uIGJvdGggcnVyYWwgYW5kIHVyYmFuIGFyZWFzIGFuZCBib3RoIGdlbmRlcnMuIEVkdWNhdGlvbiBhbmQgYXNzaXN0YW5jZSBmb3Igd29tZW4gbWF5IGJlIGVzcGVjaWFsbHkgaGVscGZ1bC4gCgojIyMgRGlmZmVyZW5jZXMgaW4gcmF0ZSBvZiBpbmNyZWFzZQoKSG93IGRvZXMgdGhlIHJhdGUgb2YgaW5jcmVhc2UgaW4gQk1JIGRpZmZlciBiZXR3ZWVuIGdyb3Vwcz8gV2hpY2ggZ3JvdXAgbWlnaHQgZXNwZWNpYWxseSBuZWVkIGF0dGVudGlvbj8KCkZpcnN0IGxldCdzIGNhbGN1bGF0ZSB0aGUgZGlmZmVyZW5jZXMgaW4gQk1JIGZyb20gMjAxNyBhbmQgMTk4NSBhbmQgYWRkIHRoaXMgdG8gb3VyIEJNSV9sb25nIGRhdGEgb2JqZWN0OgpgYGB7cn0KCkJNSV9udW1lcmljJFJ1cmFsX2RpZmZlcmVuY2UgPC0gQk1JX251bWVyaWMkUnVyYWxfQk1JXzIwMTcgLSBCTUlfbnVtZXJpYyRSdXJhbF9CTUlfMTk4NQpCTUlfbnVtZXJpYyRVcmJhbl9kaWZmZXJlbmNlIDwtIEJNSV9udW1lcmljJFVyYmFuX0JNSV8yMDE3IC0gQk1JX251bWVyaWMkVXJiYW5fQk1JXzE5ODUKQk1JX251bWVyaWMkTmF0aW9uYWxfZGlmZmVyZW5jZSA8LSBCTUlfbnVtZXJpYyROYXRpb25hbF9CTUlfMjAxNyAtIEJNSV9udW1lcmljJE5hdGlvbmFsX0JNSV8xOTg1CgpCTUlfZGlmZl9sb25nIDwtIEJNSV9udW1lcmljICU+JSBzZWxlY3QoQ291bnRyeTogTmF0aW9uYWxfZGlmZmVyZW5jZSkgJT4lIGdhdGhlcihrZXkgPSBUeXBlLCB2YWx1ZSA9IERpZmZlcmVuY2UgLCBSdXJhbF9kaWZmZXJlbmNlOk5hdGlvbmFsX2RpZmZlcmVuY2UpCmhlYWQoQk1JX2RpZmZfbG9uZykKYGBgCgpMZXQncyByZXBsYWNlICJVbml0ZWQgc3RhdGVzIG9mIEFtZXJpY2EiIHdpdGggIlVTQSIgYW5kIG1ha2UgYSBwbG90IHdpdGggdGhpcyBkYXRhIHRvIGNvbXBhcmUgdGhlIGNoYW5nZSBpbiBCTUk6CgpgYGB7cn0KCkJNSV9kaWZmX2xvbmckQ291bnRyeSA8LUJNSV9kaWZmX2xvbmckQ291bnRyeSAlPiVzdHJfcmVwbGFjZSggcGF0dGVybiA9ICJVbml0ZWQgU3RhdGVzIG9mIEFtZXJpY2EiLCByZXBsYWNlbWVudCA9ICJVU0EiKQoKCmdncGxvdChCTUlfZGlmZl9sb25nLCBhZXMoeCA9IFR5cGUsIHkgPSBEaWZmZXJlbmNlLCBjb2wgPSBUeXBlKSkgKyAKICBnZW9tX2JveHBsb3Qob3V0bGllci5zaGFwZSA9IE5BLCBjb2xvciA9ICJibGFjayIgLCBhZXMoZmlsbCA9IFR5cGUpKSArIAogIGZhY2V0X2dyaWQoflNleCkgKwogIGdlb21faml0dGVyKGRhdGE9c3Vic2V0KEJNSV9kaWZmX2xvbmcpLCBhZXMoeCA9VHlwZSwgeSA9RGlmZmVyZW5jZSksIHdpZHRoID0gLjIsIHNpemUgPTIsIHNoYXBlID0yMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImdyYXkiKSAgKyAKICAjIFRoaXMgd2lsbCBhZGQgdGhlIGluZGl2aWR1YWwgY291bnRyeSBkYXRhIHBvaW50cwogICMgVGhlIHNoYXBlIDIxIGFsbG93cyBmb3IgYSBkaWZmZXJlbnQgZmlsbCBhbmQgb3V0bGluZSBjb2xvciAoIHRoZSBvdXRsaW5lIGlzIHRoZSAiY29sb3IiKQogICMgVGhlIHdpZHRoIGRldGVybWluZXMgaG93IHdpZGUgdGhlIGppdHRlciBwb2ludHMgYXJlIHBsb3R0ZWQKICBnZW9tX2ppdHRlcihkYXRhPXN1YnNldChCTUlfZGlmZl9sb25nLCBDb3VudHJ5ID09ICJVU0EiKSwgYWVzKHggPVR5cGUsIHkgPURpZmZlcmVuY2UpLCB3aWR0aCA9IC4wMiwgc2l6ZSA9MTIsIHNoYXBlID0yMSwgY29sb3IgPSAiYmxhY2siLCBmaWxsID0gImdyYXkiKSArIAogICMgVGhpcyB3aWxsIGFkZCBwb2ludHMgdGhhdCBhcmUgbGFyZ2VyIGZvciB0aGUgVVNBIGRhdGEKICBnZW9tX3RleHQoZGF0YT1zdWJzZXQoQk1JX2RpZmZfbG9uZywgIENvdW50cnkgPT0gIlVTQSIpLCBhZXMoeCA9VHlwZSwgeSA9RGlmZmVyZW5jZSxsYWJlbD1Db3VudHJ5KSwgY29sb3IgPSAiYmxhY2siKSArIAogICMgVGhpcyB3aWxsIGFkZCBVU0EgbGFiZWxzIHRvIHRoZSBVU0EgcG9pbnRzCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLCAKICAjIFRoaXMgaXMgdXNlZnVsIGZvciByZW1vdmluZyB0aGUgbGVnZW5kCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1LGFuZ2xlID0gMzApLCAKICAgICAgICAjIHRoaXMgY2hhbmdlcyB0aGUgc2l6ZSBhbmQgYW5nbGUgb2YgdGhlIHggYXhpcyBwb2ludCBsYWJlbHMgCiAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDIwKSwgCiAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF90ZXh0KHNpemUgPTE1KSwgCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KHNpemUgPTE1KSwgCiAgICAgICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSkpICsKICAgICAgICAjIHRoaXMgY2hhbmdlcyB0aGUgc2l6ZSBvZiB4IGF4aXMgbGFiZWxzIGZvciB0aGUgZmFjZXQKICAgICAgICBnZ3RpdGxlKCAiQ2hhbmdlIGluIEJNSSBPdmVyIFRpbWUgYW5kIEFjcm9zcyBSZWdpb24gVHlwZSBhbmQgR2VuZGVyIiApIyBBZGQgYSBwbG90IHRpdGxlICAKCgoKYGBgCgpXZSBjYW4gbm93IHNlZSB0aGF0IHRoZSByYXRlIG9mIGNoYW5nZSBhcHBlYXJzIHRvIGJlIGxhcmdlciBpbiB0aGUgd29tZW4gY29tcGFyZWQgdG8gdGhlIG1lbi4gVGhlIGdyb3VwIHdpdGggdGhlIGxhcmdlc3QgaW5jcmVhc2UgaW4gdGhlIFVTQSBpcyB0aGUgd29tZW4gbGl2aW5nIGluIHJ1cmFsIGFyZWFzLgpUaHVzIHRoaXMgZ3JvdXAgc2hvdWxkIGJlIGVzcGVjaWFsbHkgZm9jdXNlZCBvbiB0byBpbXByb3ZlIHRoaXMgcHVibGljIGhlYWx0aCBpc3N1ZS4KCk5vdyBsZXQncyBtYWtlIGEgcGxvdCB0aGF0IHN1bW1hcml6ZXMgdGhlIGxhc3QgdHdvIHBsb3RzLiBUbyBkbyB0aGlzIHdlIHdpbGwgc2ltcGxpZnkgdGhlIG90aGVyIHR3byBwbG90cyBhbmQgdGhlbiBjb21iaW5lIHRoZW0gdG9nZXRoZXIuCgpgYGB7cn0KCiMgc2ltcGxpZmllZCBuYXRpb25hbCBtZWFucyBwbG90Ck1lYW5zX3Bsb3Q8LUJNSV9sb25nICU+JSAKICBmaWx0ZXIoU2V4ICVpbiUgYygiTWVuIiwgIldvbWVuIiksIFllYXIgJWluJSBjKCIxOTg1IiwgIjIwMTciKSwgUmVnaW9uID09ICJOYXRpb25hbCIpICU+JQpnZ3Bsb3QoYWVzKHggPSBTZXgsIHkgPSBCTUkpKSArIAogIGdlb21fYm94cGxvdChvdXRsaWVyLnNoYXBlID0gTkEsIGNvbG9yID0gImJsYWNrIiAsIGFlcyhmaWxsID0gU2V4KSkgKyAKIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJkb2RnZXJibHVlIiwgIm9yY2hpZDIiKSkrCiAgZmFjZXRfZ3JpZCh+WWVhcikgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MzAsIGxpbmV0eXBlPSJkYXNoZWQiLCBjb2xvciA9ICJyZWQiLCBzaXplID0xKSAgKyAKICBnZW9tX2ppdHRlcihkYXRhPUJNSV9sb25nIAogICAgICAgICAgICAgICAgICAgICAgICAgICU+JWZpbHRlcihTZXggJWluJSBjKCJNZW4iLCAiV29tZW4iKSwgWWVhciAlaW4lIGMoIjE5ODUiLCAiMjAxNyIpLCBSZWdpb24gPT0gIk5hdGlvbmFsIiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgYWVzKHggPVNleCwgeSA9Qk1JKSwgd2lkdGggPSAuMiwgc2l6ZSA9Miwgc2hhcGUgPTIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZ3JheSIpICsKICBnZW9tX2ppdHRlcihkYXRhPXN1YnNldChCTUlfbG9uZyAKICAgICAgICAgICAgICAgICAgICAgICAgICAlPiVmaWx0ZXIoU2V4ICVpbiUgYygiTWVuIiwgIldvbWVuIiksIFllYXIgJWluJSBjKCIxOTg1IiwgIjIwMTciKSwgUmVnaW9uID09ICJOYXRpb25hbCIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICBDb3VudHJ5ID09ICJVU0EiKSwgYWVzKHggPVNleCwgeSA9Qk1JKSwgd2lkdGggPSAuMDIsIHNpemUgPTEyLCBzaGFwZSA9MjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmF5IikgKyAKICAjIFRoaXMgd2lsbCBhZGQgcG9pbnRzIHRoYXQgYXJlIGxhcmdlciBmb3IgdGhlIFVTQSBkYXRhCiAgZ2VvbV90ZXh0KGRhdGE9c3Vic2V0KEJNSV9sb25nCiAgICAgICAgICAgICAgICAgICAgICAgICU+JWZpbHRlcihTZXggJWluJSBjKCJNZW4iLCAiV29tZW4iKSwgWWVhciAlaW4lIGMoIjE5ODUiLCAiMjAxNyIpLCBSZWdpb24gPT0gIk5hdGlvbmFsIiksCiAgICAgICAgICAgICAgICAgICAgICAgIENvdW50cnkgPT0gIlVTQSIpLCBhZXMoeCA9U2V4LCB5ID1CTUksbGFiZWw9Q291bnRyeSksIGNvbG9yID0gImJsYWNrIikgKyAKICAjIFRoaXMgd2lsbCBhZGQgVVNBIGxhYmVscyB0byB0aGUgVVNBIHBvaW50cwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgIyBUaGlzIGlzIHVzZWZ1bCBmb3IgcmVtb3ZpbmcgdGhlIGxlZ2VuZAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxhbmdsZSA9IDMwKSwgCiAgICAgICAgIyB0aGlzIGNoYW5nZXMgdGhlIHNpemUgYW5kIGFuZ2xlIG9mIHRoZSB4IGF4aXMgcG9pbnQgbGFiZWxzIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksIAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0xNSksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0xNSksIAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKQogICAKI1NpbXBsaWZpZWQgZGlmZmVyZW5jZSBwbG90IApCTUlfZGlmZl9sb25nJFR5cGUgPC1CTUlfZGlmZl9sb25nJFR5cGUgJT4lc3RyX3JlcGxhY2UoIHBhdHRlcm4gPSAiX2RpZmZlcmVuY2UiLCByZXBsYWNlbWVudCA9ICIiKQoKRGlmZl9wbG90PC1CTUlfZGlmZl9sb25nICU+JSAKICBmaWx0ZXIoU2V4ICVpbiUgYygiTWVuIiwgIldvbWVuIiksIFR5cGUgIT0gIk5hdGlvbmFsIikgJT4lCmdncGxvdCggYWVzKHggPSBUeXBlLCB5ID0gRGlmZmVyZW5jZSwgY29sID0gVHlwZSkpICsgCiAgZ2VvbV9ib3hwbG90KG91dGxpZXIuc2hhcGUgPSBOQSwgY29sb3IgPSAiYmxhY2siICwgYWVzKGZpbGwgPSBTZXgpKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKCJkb2RnZXJibHVlIiwgIm9yY2hpZDIiKSkrCiAgZmFjZXRfZ3JpZCh+U2V4KSArCiAgZ2VvbV9qaXR0ZXIoZGF0YT1CTUlfZGlmZl9sb25nICU+JSAKICAgIGZpbHRlcihTZXggJWluJSBjKCJNZW4iLCAiV29tZW4iKSwgVHlwZSAhPSAiTmF0aW9uYWwiKSAsIAogICAgYWVzKHggPVR5cGUsIHkgPURpZmZlcmVuY2UpLCB3aWR0aCA9IC4yLCBzaXplID0yLCBzaGFwZSA9MjEsIGNvbG9yID0gImJsYWNrIiwgZmlsbCA9ICJncmF5IikgICsgCiAgZ2VvbV9qaXR0ZXIoZGF0YT1zdWJzZXQoQk1JX2RpZmZfbG9uZyAlPiUgCiAgICBmaWx0ZXIoU2V4ICVpbiUgYygiTWVuIiwgIldvbWVuIiksIFR5cGUgIT0gIk5hdGlvbmFsIikgLCBDb3VudHJ5ID09ICJVU0EiKSwgCiAgICBhZXMoeCA9VHlwZSwgeSA9RGlmZmVyZW5jZSksIHdpZHRoID0gLjAyLCBzaXplID0xMiwgc2hhcGUgPTIxLCBjb2xvciA9ICJibGFjayIsIGZpbGwgPSAiZ3JheSIpICsgCiAgIyBUaGlzIHdpbGwgYWRkIHBvaW50cyB0aGF0IGFyZSBsYXJnZXIgZm9yIHRoZSBVU0EgZGF0YQogIGdlb21fdGV4dChkYXRhPXN1YnNldChCTUlfZGlmZl9sb25nICU+JSAKICAgIGZpbHRlcihTZXggJWluJSBjKCJNZW4iLCAiV29tZW4iKSwgVHlwZSAhPSAiTmF0aW9uYWwiKSAsIENvdW50cnkgPT0gIlVTQSIpLAogICAgYWVzKHggPVR5cGUsIHkgPURpZmZlcmVuY2UsbGFiZWw9Q291bnRyeSksIGNvbG9yID0gImJsYWNrIikgKyAKICAjIFRoaXMgd2lsbCBhZGQgVVNBIGxhYmVscyB0byB0aGUgVVNBIHBvaW50cwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiwgCiAgIyBUaGlzIGlzIHVzZWZ1bCBmb3IgcmVtb3ZpbmcgdGhlIGxlZ2VuZAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNSxhbmdsZSA9IDMwKSwgCiAgICAgICAgIyB0aGlzIGNoYW5nZXMgdGhlIHNpemUgYW5kIGFuZ2xlIG9mIHRoZSB4IGF4aXMgcG9pbnQgbGFiZWxzIAogICAgICAgIGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMCksIAogICAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0xNSksIAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0xNSksIAogICAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKSAjIHRoaXMgY2hhbmdlcyB0aGUgc2l6ZSBvZiB4IGF4aXMgbGFiZWxzIGZvciB0aGUgZmFjZXQKCkRpZmZfcGxvdDwtRGlmZl9wbG90ICsgbGFicyh0aXRsZSA9ICJDaGFuZ2UgaW4gQk1JIGJ5IHJlZ2lvbiIsIHggPSAiIiwgeSA9ICJJbmNyZWFzZSBpbiBCTUkgXG4gKDE5ODUgdG8gMjAxNykiKSsKICAgIHRoZW1lKHRpdGxlID0gZWxlbWVudF90ZXh0IChzaXplID0gMTIsIGZhY2UgPSAiYm9sZCIpKQpNZWFuc19wbG90IDwtTWVhbnNfcGxvdCArIGxhYnModGl0bGUgPSAiTWVhbiBCTUkgb3ZlciB0aW1lIiwgeCA9ICIiLCB5ID0gIk1lYW4gQk1JIikrCiAgICB0aGVtZSh0aXRsZSA9IGVsZW1lbnRfdGV4dCAoc2l6ZSA9IDEyLCBmYWNlID0gImJvbGQiKSkKCmNvd3Bsb3Q6OnBsb3RfZ3JpZChNZWFuc19wbG90LCBEaWZmX3Bsb3QsIGxhYmVscyA9IGMoIkEiLCAiQiIpKQoKYGBgCgpHcmVhdCwgbm93IHdlIGhhdmUgcHV0IHR3byBwbG90cyB0b2dldGhlciB1c2luZyB0aGUgYHBsb3RfZ3JpZCgpYCBmdW5jdGlvbiBvZiB0aGUgYGNvd3Bsb3RgIHBhY2thZ2UuIFRoaXMgd2F5IHdlIGNhbiBjbGVhcmx5IGNvbW11bmljYXRlIHR3byBtZXNzYWdlcy4gVGhlIGZpcnN0IGJlaW5nIHRoYXQgQk1JIGhhcyBpbmNyZWFzZWQgb3ZlciB0aW1lIGdsb2JhbGx5IGFuZCB0aGF0IG1hbnkgY291bnRyaWVzIGluY2x1ZGluZyB0aGUgVW5pdGVkIFN0YXRlcyBvZiBBbWVyaWNhIGFyZSBhcHByb2FjaGluZyBhIG1lYW4gQk1JIHRoYXQgaXMgYWJvdmUgdGhlIG9iZXNpdHkgdGhyZXNob2xkIG9mIDMwLiBXZSBjYW4gYWxzbyBzZWUgdGhhdCBXb21lbiBoYXZlIGxhcmdlciBCTUkgdmFsdWVzLCBidXQgdGhhdCBib3RoIGdlbmRlcnMgc2hvdyBpbmNyZWFzZWQgbGV2ZWxzIG92ZXIgdGltZS4gSW4gdGhlIHNlY29uZCBwbG90IHdlIGNhbiBzZWUgdGhhdCB0aGUgaW5jcmVhc2UgaW4gQk1JIGlzIG5vdCBqdXN0IGhhcHBlbmluZyBpbiAgdXJiYW4gY29tbXVuaXRpZXMsIGJ1dCBpbiBib3RoIHJ1cmFsIGFuZCB1cmJhbiBjb21tdW5pdGllcy4gSW4gZmFjdCwgV29tZW4gaW4gcnVyYWwgYXJlYXMgb2YgdGhlIFVuaXRlZCBTdGF0ZXMgb2YgQW1lcmljYSBhcHBlYXIgdG8gaGF2ZSB0aGUgbGFyZ2VzdCBpbmNyZWFzZSBpbiBCTUkuCgojIyBTdW1tYXJ5CgpXZSBoYXZlIGV2YWx1YXRlZCBCTUkgYXZlcmFnZSBlc3RpbWF0ZXMgZnJvbSAyMDAgZGlmZmVyZW50IGNvdW50cmllcyBhcm91bmQgdGhlIHdvcmxkLiBUbyBkbyBzbyB3ZSBpbXBvcnRlZCBkYXRhIGZyb20gYSBwZGYgdXNpbmcgdGhlIGBwZGZ0b29sc2AgcGFja2FnZS4gV2UgdXNlZCBgdGlkeXZlcnNlYCBwYWNrYWdlcyBzdWNoIGFzIGBkcGx5cmAsIGBzdHJpbmdyYCwgYW5kIGB0aWR5YCB0byBjbGVhbiB0aGUgZGF0YSBhbmQgZ2V0IGl0IGluIGEgd29ya2FibGUgZm9ybWF0LiBPdXIgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9jdXNlZCBvbiBldmFsdWF0aW5nIGRpZmZlcmVuY2VzIGluIEJNSSBpbiBmZW1hbGVzIGFyb3VuZCB0aGUgd29ybGQgYWNyb3NzIHRpbWUgYW5kIGJldHdlZW4gcnVyYWwgYW5kIHVyYmFuIGFyZWFzLiBXZSBmb3VuZCBhIHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYm90aCBiZXR3ZWVuIHllYXJzIGFuZCBiZXR3ZWVuIHRoZSB0eXBlIG9mIGNvbW11bml0eSB1c2luZyB0IHRlc3RzIGFuZCBub25wYXJhbWV0cmljIHRlc3RzLiBUaHVzIEJNSSBoYXMgaW5jcmVhc2VkIGluIHdvbWVuIHNpbmNlIDE5ODUuIEFsdGhvdWdoIEJNSSBlc3RpbWF0ZXMgYXJlIHNpZ25pZmljYW50bHkgaGlnaGVyIGluIFVyYmFuIGFyZWFzIGNvbXBhcmVkIHRvIHJ1cmFsIGFyZWFzLCBCTUkgZXN0aW1hdGVzIGhhdmUgaW5jcmVhc2VkIGluIGJvdGggcmVnaW9ucy4gIFVzaW5nIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB3ZSB3ZXJlIGFibGUgdG8gdmlzdWFsaXplIHRyZW5kcyBpbiB0aGUgZGF0YS4gSW1wb3J0YW50bHksIHRoZSBsYXJnZXN0IGluY3JlYXNlIGFwcGVhcnMgdG8gYmUgaW4gdGhlIHJ1cmFsIGFyZWFzIHBhcnRpY3VsYXJseSBmb3Igd29tZW4uIEFuYWx5c2VzIGxpa2UgdGhpcyBhcmUgaW1wb3J0YW50IGZvciBkZWZpbmluZyB3aGljaCBncm91cHMgY291bGQgYmVuZWZpdCB0aGUgbW9zdCBmcm9tIGludGVydmVudGlvbnMsIGVkdWNhdGlvbiwgYW5kIHBvbGljeSBjaGFuZ2VzIHdoZW4gYXR0ZW1wdGluZyB0byBtaXRpZ2F0ZSBwdWJsaWMgaGVhbHRoIGNoYWxsZW5nZXMuCgojIyMgU3VnZ2VzdGVkIEhvbWV3b3JrCgpTdHVkZW50cyBjYW4gZXZhbHVhdGUgdGhlIGNoYW5nZSBpbiBCTUkgb3ZlciB0aW1lIHVzaW5nIHRoZSBnbG9iYWwgZGF0YSBhdmFpbGFibGUgZm9yIGVhY2ggeWVhciBiZXR3ZWVuIDIwMTUgYW5kIDIwMTcuIFRoaXMgZGF0YSBjYW4gYmUgZm91bmQgW2hlcmVdKGh0dHA6Ly93d3cubmNkcmlzYy5vcmcvZG93bmxvYWRzL2JtaS9OQ0RfUmlzQ19MYW5jZXRfMjAxN19CTUlfYWdlX3N0YW5kYXJkaXNlZF93b3JsZC5jc3YpLgo=